f-spot r4107 - in trunk: . extensions extensions/DBusService src src/UI.Dialog
- From: thomasvm svn gnome org
- To: svn-commits-list gnome org
- Subject: f-spot r4107 - in trunk: . extensions extensions/DBusService src src/UI.Dialog
- Date: Thu, 26 Jun 2008 18:29:51 +0000 (UTC)
Author: thomasvm
Date: Thu Jun 26 18:29:51 2008
New Revision: 4107
URL: http://svn.gnome.org/viewvc/f-spot?rev=4107&view=rev
Log:
Turn DBus api into a service extension
Added:
trunk/extensions/DBusService/
trunk/extensions/DBusService/DBusProxy.cs
trunk/extensions/DBusService/DBusService.addin.xml
trunk/extensions/DBusService/DBusService.cs
trunk/extensions/DBusService/Makefile.am
Removed:
trunk/src/DBusProxy.cs
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/extensions/ChangeLog
trunk/extensions/Makefile.am
trunk/src/Core.cs
trunk/src/Db.cs
trunk/src/Makefile.am
trunk/src/PhotoStore.cs
trunk/src/Preferences.cs
trunk/src/UI.Dialog/PreferenceDialog.cs
trunk/src/f-spot.glade
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Thu Jun 26 18:29:51 2008
@@ -359,6 +359,7 @@
extensions/Makefile
extensions/BeagleService/Makefile
extensions/CDExport/Makefile
+extensions/DBusService/Makefile
extensions/DefaultExporters/Makefile
extensions/FlickrExport/Makefile
extensions/FlickrExport/FlickrNet/Makefile
Added: trunk/extensions/DBusService/DBusProxy.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/DBusService/DBusProxy.cs Thu Jun 26 18:29:51 2008
@@ -0,0 +1,447 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+using FSpot;
+using NDesk.DBus;
+
+namespace DBusService {
+ public delegate void RemoteUp();
+ public delegate void RemoteDown();
+
+ public class DBusException : Exception {
+ public DBusException (string message)
+ : base (message)
+ {}
+
+ public DBusException (string message, params object [] format_params)
+ : this (string.Format (message, format_params))
+ {}
+ }
+
+ public class DBusProxy {
+ public event RemoteUp RemoteUp;
+ public event RemoteDown RemoteDown;
+
+ internal void OnRemoteUp ()
+ {
+ if (RemoteUp != null)
+ RemoteUp ();
+ }
+
+ internal void OnRemoteDown ()
+ {
+ if (RemoteDown != null)
+ RemoteDown ();
+ }
+ }
+
+ public class DBusProxyFactory {
+ private const string SERVICE_PATH = "org.gnome.FSpot";
+ private const string TAG_PROXY_PATH = "/org/gnome/FSpot/TagRemoteControl";
+ private const string PHOTO_PROXY_PATH = "/org/gnome/FSpot/PhotoRemoteControl";
+
+ private static TagProxy tag_remote;
+ private static PhotoProxy photo_remote;
+
+ public static void Load (Db db)
+ {
+ tag_remote = new TagProxy (db.Tags);
+ Bus.Session.Register (SERVICE_PATH, new ObjectPath (TAG_PROXY_PATH), tag_remote);
+ tag_remote.OnRemoteUp ();
+
+ photo_remote = new PhotoProxy (db);
+ Bus.Session.Register (SERVICE_PATH, new ObjectPath (PHOTO_PROXY_PATH), photo_remote);
+ photo_remote.OnRemoteUp ();
+ }
+
+ public static void EmitRemoteDown ()
+ {
+ tag_remote.OnRemoteDown ();
+ photo_remote.OnRemoteDown ();
+ }
+
+ }
+
+ [Interface ("org.gnome.FSpot.TagRemoteControl")]
+ public interface ITagRemoteControl {
+ // info, included for backward compatibility with times
+ // where this was embedded in f-spot core
+ bool IsReadOnly ();
+
+ // get all
+ string[] GetTagNames ();
+ uint[] GetTagIds ();
+
+ // get info for one tag
+ IDictionary<string, object> GetTagByName (string name);
+ IDictionary<string, object> GetTagById (int id);
+
+ event RemoteUp RemoteUp;
+ event RemoteDown RemoteDown;
+
+ // tag creators
+ int CreateTag (string name);
+ int CreateTagWithParent (string parent, string name);
+
+ // tag removers
+ bool RemoveTagByName (string name);
+ bool RemoveTagById (int id);
+ }
+
+ // Class exposing all photos on the dbus
+ public class TagProxy : DBusProxy, ITagRemoteControl {
+ protected TagStore tag_store;
+
+ public TagStore Store {
+ get { return tag_store; }
+ }
+
+ internal TagProxy (TagStore store)
+ {
+ tag_store = store;
+ }
+
+ #region Interface methods
+ public bool IsReadOnly () {
+ return false;
+ }
+
+ public string[] GetTagNames ()
+ {
+ List<string> tags = new List<string> ();
+ AddTagNameToList (tags, tag_store.RootCategory);
+
+ return tags.ToArray ();
+ }
+
+ public uint[] GetTagIds ()
+ {
+ List<uint> tags = new List<uint> ();
+ AddTagIdToList (tags, tag_store.RootCategory);
+
+ return tags.ToArray ();
+ }
+
+ public IDictionary<string, object> GetTagByName (string name)
+ {
+ Tag t = tag_store.GetTagByName (name);
+
+ if (t == null)
+ throw new DBusException ("Tag with name {0} does not exist.", name);
+
+ return CreateDictFromTag (t);
+ }
+
+ public IDictionary<string, object> GetTagById (int id)
+ {
+ Tag t = tag_store.GetTagById (id);
+
+ if (t == null)
+ throw new DBusException ("Tag with id {0} does not exist.", id);
+
+ return CreateDictFromTag (t);
+ }
+
+ public int CreateTag (string name)
+ {
+ return CreateTagPriv (null, name);
+ }
+
+ public int CreateTagWithParent (string parent, string name)
+ {
+ Tag parent_tag = tag_store.GetTagByName (parent);
+
+ if (!(parent_tag is Category))
+ parent_tag = null;
+
+ return CreateTagPriv (parent_tag as Category, name);
+ }
+
+ public bool RemoveTagByName (string name)
+ {
+ Tag tag = tag_store.GetTagByName (name);
+
+ return RemoveTag (tag);
+ }
+
+ public bool RemoveTagById (int id)
+ {
+ Tag tag = tag_store.GetTagById (id);
+
+ return RemoveTag (tag);
+ }
+
+ #endregion
+
+ #region Helper methods
+ private void AddTagNameToList (List<string> list, Tag tag)
+ {
+ if (tag != tag_store.RootCategory)
+ list.Add (tag.Name);
+
+ if (tag is Category) {
+ foreach (Tag child in (tag as Category).Children)
+ AddTagNameToList (list, child);
+ }
+ }
+
+ private void AddTagIdToList (List<uint> list, Tag tag)
+ {
+ if (tag != tag_store.RootCategory)
+ list.Add (tag.Id);
+
+ if (tag is Category) {
+ foreach (Tag child in (tag as Category).Children)
+ AddTagIdToList (list, child);
+ }
+ }
+
+ private IDictionary<string, object> CreateDictFromTag (Tag t)
+ {
+ Dictionary<string, object> result = new Dictionary<string, object> ();
+
+ result.Add ("Id", t.Id);
+ result.Add ("Name", t.Name);
+
+ StringBuilder builder = new StringBuilder ();
+
+ if (t is Category) {
+ foreach (Tag child in (t as Category).Children) {
+ if (builder.Length > 0)
+ builder.Append (",");
+
+ builder.Append (child.Name);
+ }
+ }
+
+ result.Add ("Children", builder.ToString ());
+
+ return result;
+ }
+
+ private int CreateTagPriv (Category parent_tag, string name)
+ {
+ try {
+ Tag created = tag_store.CreateCategory (parent_tag, name);
+ return (int)created.Id;
+ }
+ catch {
+ throw new DBusException ("Failed to create tag.");
+ }
+ }
+
+ private bool RemoveTag (Tag t)
+ {
+ if (t == null)
+ return false;
+
+ try {
+ // remove tags from photos first
+ Core.Database.Photos.Remove (new Tag [] { t });
+ // then remove tag
+ tag_store.Remove (t);
+ return true;
+ }
+ catch {
+ return false;
+ }
+ }
+ #endregion
+ }
+
+
+ [Interface ("org.gnome.FSpot.PhotoRemoteControl")]
+ public interface IPhotoRemoteControl {
+ // info; included for backward compatibility
+ // with previous version where this was embedded in f-spot
+ bool IsReadOnly ();
+
+ // get all
+ uint[] GetPhotoIds ();
+
+ // import prepare
+ void PrepareRoll ();
+ void FinishRoll ();
+
+ // import
+ int ImportPhoto (string path, bool copy, string []tags);
+
+ // photo properties
+ IDictionary<string, object> GetPhotoProperties (uint id);
+
+ // photo remove
+ void RemovePhoto (uint id);
+
+ // query
+ uint[] Query (string []tags);
+
+ // events
+ event RemoteUp RemoteUp;
+ event RemoteDown RemoteDown;
+ }
+
+ // Class exposing all photos on the dbus
+ public class PhotoProxy : DBusProxy, IPhotoRemoteControl {
+ protected Db db;
+ private Roll current_roll;
+
+ public Db Database {
+ get { return db; }
+ }
+
+ internal PhotoProxy (Db db)
+ {
+ this.db = db;
+ }
+
+ public bool IsReadOnly ()
+ {
+ return false;
+ }
+
+ public uint[] GetPhotoIds ()
+ {
+ List<uint> ids = new List<uint> ();
+
+ foreach (Photo p in QueryAll ())
+ ids.Add (p.Id);
+
+ return ids.ToArray ();
+ }
+
+ public IDictionary<string, object> GetPhotoProperties (uint id)
+ {
+ Dictionary<string, object> dict = new Dictionary<string, object> ();
+
+ Photo p = db.Photos.Get (id) as Photo;
+
+ if (p == null)
+ throw new DBusException ("Photo with id {0} does not exist.", id);
+
+ dict.Add ("Uri", p.DefaultVersionUri.ToString());
+ dict.Add ("Id", p.Id);
+ dict.Add ("Name", p.Name);
+ dict.Add ("Description", p.Description ?? string.Empty);
+
+ StringBuilder builder = new StringBuilder ();
+
+ foreach (Tag t in p.Tags) {
+ if (builder.Length > 0)
+ builder.Append (",");
+
+ builder.AppendFormat (t.Name);
+ }
+
+ dict.Add ("Tags", builder.ToString ());
+
+ return dict;
+ }
+
+ public uint[] Query (string []tags)
+ {
+ List<Tag> tag_list = GetTagsByNames (tags);
+
+ Photo []photos = db.Photos.Query (tag_list.ToArray ());
+
+ uint []ids = new uint[photos.Length];
+
+ for (int i = 0; i < ids.Length; i++)
+ ids[i] = photos[i].Id;
+
+ return ids;
+ }
+
+ protected Photo[] QueryAll ()
+ {
+ return db.Photos.Query ((Tag [])null);
+ }
+
+ protected List<Tag> GetTagsByNames (string []names)
+ {
+ // add tags that exist in tag store
+ List<Tag> tag_list = new List<Tag> ();
+
+ foreach (string tag_name in names) {
+ Tag t = db.Tags.GetTagByName (tag_name);
+
+ if (t == null)
+ continue;
+
+ tag_list.Add (t);
+ }
+
+ return tag_list;
+ }
+
+ public void PrepareRoll ()
+ {
+ if (current_roll != null)
+ return;
+
+ current_roll = db.Rolls.Create ();
+ }
+
+ public void FinishRoll ()
+ {
+ current_roll = null;
+ }
+
+ public int ImportPhoto (string path, bool copy, string []tags)
+ {
+ if (current_roll == null)
+ throw new DBusException ("You must use PrepareRoll before you can import a photo.");
+
+ // add tags that exist in tag store
+ List<Tag> tag_list = GetTagsByNames (tags);
+
+ Gdk.Pixbuf pixbuf = null;
+
+ // FIXME: this is more or less a copy of the file import backend code
+ // this should be streamlined
+ try {
+ string new_path = path;
+
+ if (copy)
+ new_path = FileImportBackend.ChooseLocation (path);
+
+ if (new_path != path)
+ System.IO.File.Copy (path, new_path);
+
+ Photo created = db.Photos.CreateOverDBus (new_path, path, current_roll.Id, out pixbuf);
+
+ try {
+ File.SetAttributes (new_path, File.GetAttributes (new_path) & ~FileAttributes.ReadOnly);
+ DateTime create = File.GetCreationTime (path);
+ File.SetCreationTime (new_path, create);
+ DateTime mod = File.GetLastWriteTime (path);
+ File.SetLastWriteTime (new_path, mod);
+ } catch (IOException) {
+ // we don't want an exception here to be fatal.
+ }
+
+ // attach tags we got
+ if (tag_list.Count > 0) {
+ created.AddTag (tag_list.ToArray ());
+ db.Photos.Commit (created);
+ }
+
+ return (int)created.Id;
+ // indicate failure
+ } catch {
+ throw new DBusException ("Failed to import the photo.");
+ }
+ }
+
+ public void RemovePhoto (uint id)
+ {
+ Photo p = db.Photos.Get (id) as Photo;
+
+ if (p == null)
+ throw new DBusException ("Photo with id {0} does not exist.", id);
+
+ db.Photos.RemoveOverDBus (p);
+ }
+ }
+}
Added: trunk/extensions/DBusService/DBusService.addin.xml
==============================================================================
--- (empty file)
+++ trunk/extensions/DBusService/DBusService.addin.xml Thu Jun 26 18:29:51 2008
@@ -0,0 +1,17 @@
+<Addin namespace="FSpot"
+ id="DBusService"
+ version="0.4.4.0"
+ description="Expose F-Spot Photos over DBus"
+ author="Thomas Van Machelen"
+ url="http://f-spot.org/Extensions"
+ defaultEnabled="false"
+ category="Services">
+ <Dependencies>
+ <Addin id="Core" version="0.4.4.2"/>
+ </Dependencies>
+ <Extension path = "/FSpot/Services">
+ <Service class="DBusService.DBusService"/>
+ </Extension>
+</Addin>
+
+
Added: trunk/extensions/DBusService/DBusService.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/DBusService/DBusService.cs Thu Jun 26 18:29:51 2008
@@ -0,0 +1,41 @@
+/*
+ * DBusService.DBusService.cs
+ *
+ * Author(s):
+ * Thomas Van Machelen <thomas vanmachelen gmail com>
+ *
+ * This is free software. See COPYING for details.
+ *
+ */
+
+using System;
+using FSpot;
+using FSpot.Extensions;
+using FSpot.Utils;
+
+namespace DBusService {
+ public class DBusService : IService
+ {
+ public bool Start ()
+ {
+ uint timer = Log.InformationTimerStart ("Starting DBusService");
+ try {
+ DBusProxyFactory.Load (Core.Database);
+ } catch {
+ Log.Warning ("unable init DBus service");
+ }
+ Log.DebugTimerPrint (timer, "DBusService startup took {0}");
+ return true;
+ }
+
+ public bool Stop ()
+ {
+ uint timer = Log.InformationTimerStart ("Stopping DBusService");
+
+ DBusProxyFactory.EmitRemoteDown ();
+
+ Log.DebugTimerPrint (timer, "DBusService stop took {0}");
+ return true;
+ }
+ }
+}
Added: trunk/extensions/DBusService/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/extensions/DBusService/Makefile.am Thu Jun 26 18:29:51 2008
@@ -0,0 +1,47 @@
+include $(top_srcdir)/Makefile.include
+
+PLUGIN_NAME = DBusService
+
+PLUGIN_MANIFEST = $(PLUGIN_NAME).addin.xml
+
+PLUGIN_ASSEMBLY = $(PLUGIN_NAME).dll
+
+PLUGIN_SOURCES = \
+ $(srcdir)/DBusService.cs \
+ $(srcdir)/DBusProxy.cs
+
+
+REFS = \
+ -pkg:gtk-sharp-2.0 \
+ -r:../../src/f-spot.exe \
+ -r:../../src/FSpot.Core.dll \
+ -r:../../src/FSpot.Utils.dll \
+ $(LINK_DBUS)
+
+PKGS =
+
+RESOURCES = \
+ -resource:$(srcdir)/$(PLUGIN_MANIFEST)
+
+all: $(PLUGIN_ASSEMBLY)
+
+mpack: $(PLUGIN_ASSEMBLY)
+ mautil p $(PLUGIN_ASSEMBLY)
+
+$(PLUGIN_ASSEMBLY): $(PLUGIN_SOURCES) $(PLUGIN_MANIFEST)
+ $(CSC_LIB) -out:$@ $(CSC_DEFINES) $(PLUGIN_SOURCES) $(REFS) $(PKGS) $(ASSEMBLIES) $(RESOURCES)
+
+plugindir = $(pkglibdir)/extensions
+
+plugin_DATA = \
+ $(PLUGIN_ASSEMBLY)
+
+EXTRA_DIST = \
+ $(PLUGIN_SOURCES) \
+ $(PLUGIN_MANIFEST) \
+ $(PLUGIN_NAME).glade
+
+CLEANFILES = \
+ $(PLUGIN_ASSEMBLY) \
+ $(PLUGIN_ASSEMBLY).mdb \
+ *.mpack
Modified: trunk/extensions/Makefile.am
==============================================================================
--- trunk/extensions/Makefile.am (original)
+++ trunk/extensions/Makefile.am Thu Jun 26 18:29:51 2008
@@ -1,5 +1,6 @@
SUBDIRS = \
BeagleService \
+ DBusService \
CDExport \
GalleryExport \
FlickrExport \
Modified: trunk/src/Core.cs
==============================================================================
--- trunk/src/Core.cs (original)
+++ trunk/src/Core.cs Thu Jun 26 18:29:51 2008
@@ -269,8 +269,6 @@
{
toplevels.Remove (sender);
if (toplevels.Count == 0) {
- if (db != null)
- db.EmitDown ();
// FIXME
// Should use Application.Quit(), but for that to work we need to terminate the threads
// first too.
Modified: trunk/src/Db.cs
==============================================================================
--- trunk/src/Db.cs (original)
+++ trunk/src/Db.cs Thu Jun 26 18:29:51 2008
@@ -248,18 +248,12 @@
job_store = new JobStore (Database, new_db);
photo_store = new PhotoStore (Database, new_db);
- FSpot.DBusProxyFactory.Load (this);
-
Database.CommitTransaction ();
empty = new_db;
Log.DebugTimerPrint (timer, "Db Initialization took {0}");
}
- public void EmitDown () {
- FSpot.DBusProxyFactory.EmitRemoteDown ();
- }
-
public bool Empty {
get {
return empty;
Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Thu Jun 26 18:29:51 2008
@@ -85,7 +85,6 @@
$(srcdir)/Core/PhotoVersion.cs \
$(srcdir)/DateCommands.cs \
$(srcdir)/Db.cs \
- $(srcdir)/DBusProxy.cs \
$(srcdir)/DependentListStore.cs \
$(srcdir)/DirectoryAdaptor.cs \
$(srcdir)/DirectoryCollection.cs \
Modified: trunk/src/PhotoStore.cs
==============================================================================
--- trunk/src/PhotoStore.cs (original)
+++ trunk/src/PhotoStore.cs Thu Jun 26 18:29:51 2008
@@ -462,14 +462,14 @@
public event ItemsAddedHandler ItemsAddedOverDBus;
public event ItemsRemovedHandler ItemsRemovedOverDBus;
- internal Photo CreateOverDBus (string new_path, string orig_path, uint roll_id, out Gdk.Pixbuf pixbuf) {
+ public Photo CreateOverDBus (string new_path, string orig_path, uint roll_id, out Gdk.Pixbuf pixbuf) {
Photo photo = Create (new_path, orig_path, roll_id, out pixbuf);
EmitAddedOverDBus (photo);
return photo;
}
- internal void RemoveOverDBus (Photo photo) {
+ public void RemoveOverDBus (Photo photo) {
Remove (photo);
EmitRemovedOverDBus (photo);
}
Modified: trunk/src/Preferences.cs
==============================================================================
--- trunk/src/Preferences.cs (original)
+++ trunk/src/Preferences.cs Thu Jun 26 18:29:51 2008
@@ -57,8 +57,6 @@
public const string IMPORT_GUI_ROLL_HISTORY = "/apps/f-spot/import/gui_roll_history";
- public const string DBUS_READ_ONLY = "/apps/f-spot/dbus/read_only";
-
public const string SCREENSAVER_TAG = "/apps/f-spot/screensaver/tag_id";
public const string STORAGE_PATH = "/apps/f-spot/import/storage_path";
@@ -138,8 +136,6 @@
case SHOW_DATES:
case SHOW_RATINGS:
case VIEWER_SHOW_FILENAMES:
- case DBUS_READ_ONLY:
- return true;
case TAG_ICON_SIZE:
return (int) Tag.IconSize.Medium;
Modified: trunk/src/UI.Dialog/PreferenceDialog.cs
==============================================================================
--- trunk/src/UI.Dialog/PreferenceDialog.cs (original)
+++ trunk/src/UI.Dialog/PreferenceDialog.cs Thu Jun 26 18:29:51 2008
@@ -76,8 +76,6 @@
photosdir_chooser.SetCurrentFolder(Global.PhotoDirectory);
photosdir_chooser.Sensitive = false;
}
- LoadPreference (Preferences.DBUS_READ_ONLY);
-
#if FALSE
Gtk.CellRendererText name_cell = new Gtk.CellRendererText ();
Gtk.CellRendererText desc_cell = new Gtk.CellRendererText ();
@@ -251,14 +249,6 @@
Preferences.Set (Preferences.METADATA_EMBED_IN_IMAGE, metadata_check.Active);
}
- void DBusReadOnlyToggled (object sender, System.EventArgs args)
- {
- Preferences.Set (Preferences.DBUS_READ_ONLY, !dbus_check.Active);
-
- DBusProxyFactory.EmitRemoteDown ();
- DBusProxyFactory.Load (MainWindow.Toplevel.Database);
- }
-
void HandlePhotosdirChanged (object sender, System.EventArgs args)
{
Preferences.Set (Preferences.STORAGE_PATH, photosdir_chooser.Filename);
@@ -308,9 +298,6 @@
case Preferences.STORAGE_PATH:
photosdir_chooser.SetCurrentFolder (Preferences.Get<string> (key));
break;
- case Preferences.DBUS_READ_ONLY:
- dbus_check.Active = !(Preferences.Get<bool> (key));
- break;
case Preferences.GTK_RC:
themenone_radio.Active = (Preferences.Get<string> (key) == String.Empty);
themecustom_radio.Active = (Preferences.Get<string> (key) != String.Empty);
Modified: trunk/src/f-spot.glade
==============================================================================
--- trunk/src/f-spot.glade (original)
+++ trunk/src/f-spot.glade Thu Jun 26 18:29:51 2008
@@ -6446,74 +6446,6 @@
</packing>
</child>
<child>
- <widget class="GtkFrame" id="frame27">
- <property name="visible">True</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">GTK_SHADOW_NONE</property>
- <child>
- <widget class="GtkAlignment" id="alignment28">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <widget class="GtkVBox" id="vbox18">
- <property name="visible">True</property>
- <child>
- <widget class="GtkCheckButton" id="dbus_check">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Allow other programs to manipulate F-Spot</property>
- <property name="use_underline">True</property>
- <property name="response_id">0</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="DBusReadOnlyToggled"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label8">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">12</property>
- <property name="label" translatable="yes"><small><i>Enable this option if you want to allow other programs to import or delete photos and tags over DBus.</i></small></property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="padding">12</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="label9">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><b>Interoperability</b></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="type">label_item</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
<widget class="GtkFrame" id="frame9">
<property name="visible">True</property>
<property name="shadow_type">GTK_SHADOW_NONE</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]