1

I'm not finding, on the Qt documentation, a section explaining about the qApp->setProperty() option (it is probably there, but I can't find it). Can someone explain to me basically how it works and when should I use it?

I'm asking it because I need to define the path of my database file as a "global constant", to be used in many classes, so I was thinking in set it using the setProperty function.

For example:

qApp->setProperty("DATABASE_PATH", "C:/../Database.db");

Then, access it using:

qApp->property("DATABASE_PATH").toString();

Can I do that or there is a better/correct way to do so?

KelvinS
  • 2,870
  • 8
  • 34
  • 67

2 Answers2

2

This function is not displayed in the main view of the QApplication documentation.

On this page there is a section called: List of all members, including inherited members, in them you will find all the properties that you have either exclusive or your parent classes.

Looking for this function is established in QObject:

bool QObject::setProperty(const char *name, const QVariant &value)

Sets the value of the object's name property to value.

If the property is defined in the class using Q_PROPERTY then true is returned on success and false otherwise. If the property is not defined using Q_PROPERTY, and therefore not listed in the meta-object, it is added as a dynamic property and false is returned.

Information about all available properties is provided through the metaObject() and dynamicPropertyNames().

Dynamic properties can be queried again using property() and can be removed by setting the property value to an invalid QVariant. Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent to be sent to the object.

Note: Dynamic properties starting with "q" are reserved for internal purposes.

See also property(), metaObject(), dynamicPropertyNames(), and QMetaProperty::write().

setProperty is used to expose a property through its name, and if you could use it in your case since qApp is a pointer that can be accessed by your entire program.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks for the answer but I still don't understand when should I use it and if I can use it in the example shown in the question. – KelvinS May 31 '17 at 19:04
2

Properties are provided by QObject, which QApplication is-a.

The properties you're using are so-called dynamic properties and are very useful when you have an object that you can't otherwise modify, but need to add some additional data to it.

Note that it's really bad style to pass string literals to property or setProperty: you can easily let typos sneak in. Because of that, properties should only be used with unique constant names:

// common code
// proplist.h

PROPLIST_PROP(databasePath)
PROPLIST_PROP(foo)

// interface
// properties.h

#define PROPLIST_PROP(name) static const char name[];
struct Prop {
  #include "proplist.h"
};
#undef PROPLIST_PROP

// implementation
// properties.cpp

#define PROPLIST_PROP(name) const char Prop::name[] = #name;
#include "proplist.h"

// use
obj.setProperty(Prop::databasePath, ...);
auto path = obj.property(Prop::databasePath).toString();

You can encapsulate the type and the name of a property:

// common code
// proplist.h

PROPLIST_PROP(QString, databasePath)
PROPLIST_PROP(int, foo)

// interface
#define DECLARE_PROPERTY(type_, name_) using name_ = Property<type_, struct name_>;
#define DEFINE_PROPERTY(type_, name_) const char name_::name[] = #name_;

template <typename T, typename Tag> Property {
  static const char name[];
  static T get(QObject * obj) {
    return obj->property(name).value<T>();
  }
  static void set(QObject * obj, const T& val) {
    obj->setProperty(name, QVariant::fromValue(val));
  }
};

#define PROPLIST_PROP DECLARE_PROPERTY
namespace Prop {
  #include "proplist.h"
}
#undef PROPLIST_PROP

// implementation
#define PROPLIST_PROP DEFINE_PROPERTY
namespace Prop {
  #include "proplist.h"
}    

// use
Prop::DatabasePath::set(obj, ...);
auto path = Prop::DatabasePath::get(obj);

The major issue I see is that most likely you're abusing the property system and instead might benefit from a global settings object:

// interface
struct SettingsData {
  SettingsData() { Q_ASSERT(!m_instance); m_instance = this; }
  ~SettingsData() { m_instance = nullptr; }
  static SettingsData * instance() { return m_instance; }

  QString databasePath = "some default value";
  int gizmoSize = 44;
private:
  static SettingsData * m_instance;
};

SettingsData & Settings() { return *SettingsData::instance(); }

// implementation
SettingsData * SettingsData::m_instance;

// use
int main(int argc, char ** argv) {
  QApplication app(argc, argv);
  SettingsData settings;
  ...
}

void test() {
  Settings().databasePath = ...;
  auto path = Settings().databasePath;
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313