2009-07-02 12:00:45 -04:00
|
|
|
/* $Id: generate_extra_defs.cc 793 2009-03-09 17:49:00Z daniel $ */
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
/* generate_extra_defs.cc
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001 The Free Software Foundation
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
2009-07-02 12:00:45 -04:00
|
|
|
* modify it under the terms of the GNU Library General Public
|
2008-06-02 17:41:35 -04:00
|
|
|
* License as published by the Free Software Foundation; either
|
2009-07-02 12:00:45 -04:00
|
|
|
* version 2 of the License, or (at your option) any later version.
|
2008-06-02 17:41:35 -04:00
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2009-07-02 12:00:45 -04:00
|
|
|
* Library General Public License for more details.
|
2008-06-02 17:41:35 -04:00
|
|
|
*
|
2009-07-02 12:00:45 -04:00
|
|
|
* You should have received a copy of the GNU Library General Public
|
2008-06-02 17:41:35 -04:00
|
|
|
* License along with this library; if not, write to the Free
|
|
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "generate_extra_defs.h"
|
2009-07-02 09:12:38 -04:00
|
|
|
#include <algorithm>
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
std::string get_properties(GType gtype)
|
|
|
|
{
|
|
|
|
std::string strResult;
|
|
|
|
std::string strObjectName = g_type_name(gtype);
|
|
|
|
|
|
|
|
//Get the list of properties:
|
2009-07-02 09:12:38 -04:00
|
|
|
GParamSpec** ppParamSpec = 0;
|
2008-06-02 17:41:35 -04:00
|
|
|
guint iCount = 0;
|
2009-07-02 09:12:38 -04:00
|
|
|
if(G_TYPE_IS_OBJECT(gtype))
|
|
|
|
{
|
|
|
|
GObjectClass* pGClass = G_OBJECT_CLASS(g_type_class_ref(gtype));
|
|
|
|
ppParamSpec = g_object_class_list_properties (pGClass, &iCount);
|
|
|
|
g_type_class_unref(pGClass);
|
|
|
|
|
|
|
|
if(!ppParamSpec)
|
|
|
|
{
|
|
|
|
strResult += ";; Warning: g_object_class_list_properties() returned NULL for " + std::string(g_type_name(gtype)) + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (G_TYPE_IS_INTERFACE(gtype))
|
|
|
|
{
|
|
|
|
gpointer pGInterface = g_type_default_interface_ref(gtype);
|
|
|
|
if(pGInterface) //We check because this fails for G_TYPE_VOLUME, for some reason.
|
|
|
|
{
|
|
|
|
ppParamSpec = g_object_interface_list_properties(pGInterface, &iCount);
|
|
|
|
g_type_default_interface_unref(pGInterface);
|
|
|
|
|
|
|
|
if(!ppParamSpec)
|
|
|
|
{
|
|
|
|
strResult += ";; Warning: g_object_interface_list_properties() returned NULL for " + std::string(g_type_name(gtype)) + "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//This extra check avoids an occasional crash, for instance for GVolume
|
|
|
|
if(!ppParamSpec)
|
|
|
|
iCount = 0;
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
for(guint i = 0; i < iCount; i++)
|
|
|
|
{
|
|
|
|
GParamSpec* pParamSpec = ppParamSpec[i];
|
|
|
|
if(pParamSpec)
|
|
|
|
{
|
|
|
|
//Name and type:
|
2009-07-02 09:12:38 -04:00
|
|
|
const std::string strName = g_param_spec_get_name(pParamSpec);
|
|
|
|
const std::string strTypeName = G_PARAM_SPEC_TYPE_NAME(pParamSpec);
|
|
|
|
|
2008-06-02 17:41:35 -04:00
|
|
|
const gchar* pchBlurb = g_param_spec_get_blurb(pParamSpec);
|
2009-07-02 09:12:38 -04:00
|
|
|
std::string strDocs = (pchBlurb) ? pchBlurb : "";
|
|
|
|
// Quick hack to get rid of nested double quotes:
|
|
|
|
std::replace(strDocs.begin(), strDocs.end(), '"', '\'');
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
strResult += "(define-property " + strName + "\n";
|
|
|
|
strResult += " (of-object \"" + strObjectName + "\")\n";
|
|
|
|
strResult += " (prop-type \"" + strTypeName + "\")\n";
|
|
|
|
strResult += " (docs \"" + strDocs + "\")\n";
|
|
|
|
|
|
|
|
//Flags:
|
|
|
|
GParamFlags flags = pParamSpec->flags;
|
|
|
|
bool bReadable = (flags & G_PARAM_READABLE) == G_PARAM_READABLE;
|
|
|
|
bool bWritable = (flags & G_PARAM_WRITABLE) == G_PARAM_WRITABLE;
|
|
|
|
bool bConstructOnly = (flags & G_PARAM_CONSTRUCT_ONLY) == G_PARAM_CONSTRUCT_ONLY;
|
|
|
|
|
|
|
|
//#t and #f aren't documented, but I guess that it's correct based on the example in the .defs spec.
|
|
|
|
const std::string strTrue = "#t";
|
|
|
|
const std::string strFalse = "#f";
|
|
|
|
|
|
|
|
strResult += " (readable " + (bReadable ? strTrue : strFalse) + ")\n";
|
|
|
|
strResult += " (writable " + (bWritable ? strTrue : strFalse) + ")\n";
|
|
|
|
strResult += " (construct-only " + (bConstructOnly ? strTrue : strFalse) + ")\n";
|
|
|
|
|
|
|
|
strResult += ")\n\n"; //close (define-property
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(ppParamSpec);
|
|
|
|
|
|
|
|
return strResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_type_name(GType gtype) //Adds a * if necessary.
|
|
|
|
{
|
|
|
|
std::string strTypeName = g_type_name(gtype);
|
|
|
|
|
|
|
|
if( g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_BOXED) )
|
|
|
|
strTypeName += "*"; //Add * to show that it's a pointer.
|
|
|
|
else if( g_type_is_a(gtype, G_TYPE_STRING) )
|
|
|
|
strTypeName = "gchar*"; //g_type_name() returns "gchararray".
|
|
|
|
|
|
|
|
return strTypeName;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_type_name_parameter(GType gtype)
|
|
|
|
{
|
|
|
|
std::string strTypeName = get_type_name(gtype);
|
|
|
|
|
|
|
|
//All signal parameters that are registered as GTK_TYPE_STRING are actually const gchar*.
|
|
|
|
if(strTypeName == "gchar*")
|
|
|
|
strTypeName = "const-gchar*";
|
|
|
|
|
|
|
|
return strTypeName;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string get_type_name_signal(GType gtype)
|
|
|
|
{
|
|
|
|
return get_type_name_parameter(gtype); //At the moment, it needs the same stuff.
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string get_signals(GType gtype)
|
|
|
|
{
|
|
|
|
std::string strResult;
|
|
|
|
std::string strObjectName = g_type_name(gtype);
|
|
|
|
|
|
|
|
gpointer gclass_ref = 0;
|
2009-07-02 09:12:38 -04:00
|
|
|
gpointer ginterface_ref = 0;
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
if(G_TYPE_IS_OBJECT(gtype))
|
|
|
|
gclass_ref = g_type_class_ref(gtype); //Ensures that class_init() is called.
|
2009-07-02 09:12:38 -04:00
|
|
|
else if(G_TYPE_IS_INTERFACE(gtype))
|
|
|
|
ginterface_ref = g_type_default_interface_ref(gtype); //install signals.
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
//Get the list of signals:
|
|
|
|
guint iCount = 0;
|
|
|
|
guint* pIDs = g_signal_list_ids (gtype, &iCount);
|
|
|
|
|
|
|
|
//Loop through the list of signals:
|
|
|
|
if(pIDs)
|
|
|
|
{
|
|
|
|
for(guint i = 0; i < iCount; i++)
|
|
|
|
{
|
|
|
|
guint signal_id = pIDs[i];
|
|
|
|
|
|
|
|
//Name:
|
|
|
|
std::string strName = g_signal_name(signal_id);
|
|
|
|
strResult += "(define-signal " + strName + "\n";
|
|
|
|
strResult += " (of-object \"" + strObjectName + "\")\n";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Other information about the signal:
|
|
|
|
GSignalQuery signalQuery = { 0, 0, 0, GSignalFlags(0), 0, 0, 0, };
|
|
|
|
g_signal_query(signal_id, &signalQuery);
|
|
|
|
|
|
|
|
//Return type:
|
|
|
|
std::string strReturnTypeName = get_type_name_signal( signalQuery.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE ); //The type is mangled with a flag. Hacky.
|
|
|
|
//bool bReturnTypeHasStaticScope = (signalQuery.return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == G_SIGNAL_TYPE_STATIC_SCOPE;
|
|
|
|
strResult += " (return-type \"" + strReturnTypeName + "\")\n";
|
|
|
|
|
|
|
|
|
|
|
|
//When:
|
|
|
|
{
|
|
|
|
bool bWhenFirst = (signalQuery.signal_flags & G_SIGNAL_RUN_FIRST) == G_SIGNAL_RUN_FIRST;
|
|
|
|
bool bWhenLast = (signalQuery.signal_flags & G_SIGNAL_RUN_LAST) == G_SIGNAL_RUN_LAST;
|
|
|
|
|
|
|
|
std::string strWhen = "unknown";
|
|
|
|
|
|
|
|
if(bWhenFirst && bWhenLast)
|
|
|
|
strWhen = "both";
|
|
|
|
else if(bWhenFirst)
|
|
|
|
strWhen = "first";
|
|
|
|
else if(bWhenLast)
|
|
|
|
strWhen = "last";
|
|
|
|
|
|
|
|
strResult += " (when \"" + strWhen + "\")\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//Loop through the list of parameters:
|
|
|
|
const GType* pParameters = signalQuery.param_types;
|
|
|
|
if(pParameters)
|
|
|
|
{
|
|
|
|
strResult += " (parameters\n";
|
|
|
|
|
|
|
|
for(unsigned i = 0; i < signalQuery.n_params; i++)
|
|
|
|
{
|
|
|
|
GType typeParamMangled = pParameters[i];
|
|
|
|
|
|
|
|
//Parameter name:
|
|
|
|
//TODO: How can we get the real parameter name?
|
|
|
|
gchar* pchNum = g_strdup_printf("%d", i);
|
|
|
|
std::string strParamName = "p" + std::string(pchNum);
|
|
|
|
g_free(pchNum);
|
|
|
|
pchNum = 0;
|
|
|
|
|
|
|
|
//Just like above, for the return type:
|
|
|
|
std::string strTypeName = get_type_name_signal( typeParamMangled & ~G_SIGNAL_TYPE_STATIC_SCOPE ); //The type is mangled with a flag. Hacky.
|
|
|
|
//bool bReturnTypeHasStaticScope = (typeParamMangled & G_SIGNAL_TYPE_STATIC_SCOPE) == G_SIGNAL_TYPE_STATIC_SCOPE;
|
|
|
|
|
|
|
|
strResult += " '(\"" + strTypeName + "\" \"" + strParamName + "\")\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
strResult += " )\n"; //close (properties
|
|
|
|
}
|
|
|
|
|
|
|
|
strResult += ")\n\n"; //close (define=signal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free(pIDs);
|
|
|
|
|
|
|
|
if(gclass_ref)
|
|
|
|
g_type_class_unref(gclass_ref); //to match the g_type_class_ref() above.
|
2009-07-02 09:12:38 -04:00
|
|
|
else if(ginterface_ref)
|
|
|
|
g_type_default_interface_unref(ginterface_ref); // for interface ref above.
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
return strResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string get_defs(GType gtype)
|
|
|
|
{
|
|
|
|
std::string strObjectName = g_type_name(gtype);
|
|
|
|
std::string strDefs = ";; From " + strObjectName + "\n\n";
|
|
|
|
|
2009-07-02 09:12:38 -04:00
|
|
|
if(G_TYPE_IS_OBJECT(gtype) || G_TYPE_IS_INTERFACE(gtype))
|
|
|
|
{
|
|
|
|
strDefs += get_signals(gtype);
|
2008-06-02 17:41:35 -04:00
|
|
|
strDefs += get_properties(gtype);
|
2009-07-02 09:12:38 -04:00
|
|
|
}
|
2008-06-02 17:41:35 -04:00
|
|
|
|
|
|
|
return strDefs;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|