Skip to content

Instantly share code, notes, and snippets.

@rodolforg
Created July 24, 2020 05:24
Show Gist options
  • Select an option

  • Save rodolforg/802222eb41287da744646529615d91e2 to your computer and use it in GitHub Desktop.

Select an option

Save rodolforg/802222eb41287da744646529615d91e2 to your computer and use it in GitHub Desktop.
How to read/parse simple custom properties from glade file for a custom widget in gtkmm
// Sample code showing how to read/parse properties from glade file for a custom widget in gtkmm
//
// On linux, you can build it with:
// g++ -o simple simple.cpp `pkg-config --cflags --libs gtkmm-3.0`
#include <gtkmm.h>
#include <iostream>
#include <string>
static Glib::RefPtr<Gtk::Builder> load_interface(const char *filename);
// My custom widget
class MyLabel : public Gtk::Label
{
// my custom property (int)
Glib::Property<int> property_my_max_chars_;
public:
MyLabel()
: Glib::ObjectBase("my_label"), // this way, our class is named gtkmm__CustomObject_my_label for Glib
Gtk::Label(),
property_my_max_chars_(*this, "my_max_chars", 5) // set the property on constructor.
// "my_max_chars" is its name (used by Gtk::Inspector, Gtk::Builder, etc)
// 5 is its default value. Not mandatory, but as it's an int...
{
init();
}
// constructor used by Gtk::Builder (actually constructor called indirectly from C library)
MyLabel(BaseObjectType* cobject)
: Glib::ObjectBase("my_label"),
Gtk::Label(cobject),
property_my_max_chars_(*this, "my_max_chars", 5)
{
init();
}
// get/set access to my custom property
Glib::PropertyProxy<int> property_my_max_chars() { return property_my_max_chars_.get_proxy(); }
// get-only access to my custom property
Glib::PropertyProxy_ReadOnly<int> property_my_max_chars() const { return property_my_max_chars_.get_proxy(); }
private:
void init() {
// if someone sets a new value to my custom property... (example: property_my_max_chars() = 4; )
property_my_max_chars().signal_changed().connect( sigc::mem_fun(*this, &MyLabel::on_my_max_chars_change) ); // could call redact() directly...
property_label().signal_changed().connect( sigc::mem_fun(*this, &MyLabel::on_text_change) ); // could call redact() directly...
redact();
}
void on_my_max_chars_change() {
redact();
}
void on_text_change() {
redact();
}
// limit the string length
void redact() {
std::string label = get_label();
int max_chars = property_my_max_chars();
if (max_chars > 0 && label.length() > max_chars)
set_label(label.substr(0, max_chars));
}
// More Gtk::Builder stuff (actually C++ - C binding)
public:
// Construct a C++ object from a parent (=base) C class object
static Glib::ObjectBase* wrap_new(GObject* o) {
auto obj = new MyLabel(GTK_LABEL(o));
if (gtk_widget_is_toplevel(GTK_WIDGET(o)))
return obj;
else
return Gtk::manage(obj);
}
// Register a "new" type in Glib and bind it to the C++ wrapper function
static void register_type() {
if (gtype)
return;
MyLabel dummy;
gtype = G_OBJECT_TYPE(dummy.gobj());
Glib::wrap_register(gtype, MyLabel::wrap_new);
}
private:
static GType gtype;
};
GType MyLabel::gtype = 0;
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv,"org.any.my");
MyLabel::register_type();
Gtk::Window window;
window.set_default_size(200, 200);
auto refBuilder = load_interface("test_my_label.glade");
if (!refBuilder) {
std::cerr << "Couldn't load the interface file" << std::endl;
return 1;
}
MyLabel * widget = nullptr;
refBuilder->get_widget("widget_mylabel", widget);
if (!widget) {
std::cerr << "Couldn't find a widget with id ='widget_mylabel'" << std::endl;
return 2;
}
window.add(*widget);
window.show_all();
return app->run(window);
}
static Glib::RefPtr<Gtk::Builder> load_interface(const char *filename)
{
auto refBuilder = Gtk::Builder::create();
try
{
refBuilder->add_from_file(filename);
}
catch(const Glib::FileError& ex)
{
std::cerr << "FileError: " << ex.what() << std::endl;
return Glib::RefPtr<Gtk::Builder>();
}
catch(const Glib::MarkupError& ex)
{
std::cerr << "MarkupError: " << ex.what() << std::endl;
return Glib::RefPtr<Gtk::Builder>();
}
catch(const Gtk::BuilderError& ex)
{
std::cerr << "BuilderError: " << ex.what() << std::endl;
return Glib::RefPtr<Gtk::Builder>();
}
return refBuilder;
}
/** test_my_label.glade
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="gtkmm__CustomObject_my_label" id="widget_mylabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">A long text</property>
<property name="my_max_chars">5</property>
</object>
</interface>
**/
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.2 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="gtkmm__CustomObject_my_label" id="widget_mylabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">A long text</property>
<property name="my_max_chars">5</property>
</object>
</interface>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment