Skip to content

Commit

Permalink
Fix QSettings
Browse files Browse the repository at this point in the history
Make it a safe API
  • Loading branch information
ogoffart committed Oct 31, 2023
1 parent 26f3dcb commit bfa80db
Showing 1 changed file with 24 additions and 39 deletions.
63 changes: 24 additions & 39 deletions qttypes/src/qtcore/qsettings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ cpp_class!(
/// Wrapper around [`QSettings`][class] class.
///
/// [class]: https://doc.qt.io/qt-5/qsettings.html
#[derive(Default)]
pub unsafe struct QSettings as "std::unique_ptr<QSettings>"
);

Expand All @@ -22,34 +21,32 @@ impl QSettings {
/// with setting `format` set to `IniFormat` and `scope` to (default) `UserScope`
///
/// [ctor]: https://doc.qt.io/qt-5/qsettings.html#QSettings-3
pub fn new(organization: &str, application: &str) -> *mut Self {
pub fn new(organization: &str, application: &str) -> Self {
let organization = QString::from(organization);
let application = QString::from(application);
cpp!(
unsafe [organization as "QString", application as "QString"] -> *mut QSettings as "QSettings*" {
QSettings* settings = new QSettings(QSettings::IniFormat, QSettings::UserScope, organization, application);
return settings;
unsafe [organization as "QString", application as "QString"] -> QSettings as "std::unique_ptr<QSettings>" {
return std::unique_ptr<QSettings>(new QSettings(QSettings::IniFormat, QSettings::UserScope, organization, application));
}
)
}

/// Wrapper around [`QSettings(const QString &fileName, QSettings::Format format, QObject *parent = nullptr)`][ctor] constructor.
///
/// [ctor]: https://doc.qt.io/qt-5/qsettings.html#QSettings
pub fn from_path(file_name: &str) -> *mut Self {
pub fn from_path(file_name: &str) -> Self {
let file_name = QString::from(file_name);
cpp!(
unsafe [file_name as "QString"] -> *mut QSettings as "QSettings*" {
QSettings* settings = new QSettings(file_name, QSettings::IniFormat);
return settings;
unsafe [file_name as "QString"] -> QSettings as "std::unique_ptr<QSettings>" {
return std::unique_ptr<QSettings>(new QSettings(file_name, QSettings::IniFormat));
}
)
}

pub fn filename(&self) -> String {
let filename: QString = cpp!(
unsafe [self as "QSettings *"] -> QString as "QString" {
return self->fileName();
unsafe [self as "QSettings **"] -> QString as "QString" {
return (*self)->fileName();
}
);
filename.to_string()
Expand All @@ -58,35 +55,35 @@ impl QSettings {
pub fn contains(&self, key: &str) -> bool {
let key = QString::from(key);
unsafe {
cpp!([self as "QSettings *", key as "QString"] -> bool as "bool" {
return self->contains(key);
cpp!([self as "QSettings **", key as "QString"] -> bool as "bool" {
return (*self)->contains(key);
})
}
}

pub fn value_bool(&self, key: &str) -> bool {
let key = QString::from(key);
unsafe {
cpp!([self as "QSettings *", key as "QString"] -> bool as "bool" {
return self->value(key).toBool();
cpp!([self as "QSettings **", key as "QString"] -> bool as "bool" {
return (*self)->value(key).toBool();
})
}
}

pub fn set_bool(&mut self, key: &str, value: bool) {
let key = QString::from(key);
unsafe {
cpp!([self as "QSettings *", key as "QString", value as "bool"] {
self->setValue(key, value);
cpp!([self as "QSettings **", key as "QString", value as "bool"] {
(*self)->setValue(key, value);
})
};
}

pub fn value_string(&self, key: &str) -> String {
let key = QString::from(key);
let val = unsafe {
cpp!([self as "QSettings *", key as "QString"] -> QString as "QString" {
return self->value(key).toString();
cpp!([self as "QSettings **", key as "QString"] -> QString as "QString" {
return (*self)->value(key).toString();
})
};
val.into()
Expand All @@ -96,49 +93,41 @@ impl QSettings {
let key = QString::from(key);
let value = QString::from(value);
unsafe {
cpp!([self as "QSettings *", key as "QString", value as "QString"] {
self->setValue(key, value);
cpp!([self as "QSettings **", key as "QString", value as "QString"] {
(*self)->setValue(key, value);
})
};
}

pub fn sync(&self) {
unsafe {
cpp!([self as "QSettings *"] {
self->sync();
cpp!([self as "QSettings **"] {
(*self)->sync();
})
};
}
}

#[test]
fn test_qsettings_filename() {
let inner = QSettings::new("qmetaobject", "qsettings");
let qsettings = unsafe { inner.as_ref().unwrap() };
let qsettings = QSettings::new("qmetaobject", "qsettings");

assert!(
qsettings.filename().ends_with("/qmetaobject/qsettings.ini"),
"'{}' does not end with '/qmetaobject/qsettings.ini'",
qsettings.filename()
);

drop(qsettings);
drop(inner);
}

#[test]
fn test_qsettings_new_from_path() {
let inner = QSettings::from_path("/tmp/my_settings.conf");
let qsettings = unsafe { inner.as_ref().unwrap() };
let qsettings = QSettings::from_path("/tmp/my_settings.conf");

assert!(
qsettings.filename().ends_with("/tmp/my_settings.conf"),
"'{}' does not end with '/tmp/my_settings.conf'",
qsettings.filename()
);

drop(qsettings);
drop(inner);
}

#[test]
Expand All @@ -147,8 +136,7 @@ fn test_qsettings_values() {
let config_pathbuf = temp_dir.path().join("qsettings.conf");
let config_file = config_pathbuf.to_str().unwrap();

let inner = QSettings::from_path(config_file);
let qsettings = unsafe { inner.as_mut().unwrap() };
let mut qsettings = QSettings::from_path(config_file);

qsettings.set_bool("test_true", false);
qsettings.set_bool("test_false", true);
Expand All @@ -165,10 +153,8 @@ fn test_qsettings_values() {
assert_eq!(qsettings.value_string("test_emoji"), "🦀");

drop(qsettings);
drop(inner);

let inner = QSettings::from_path(config_file);
let qsettings = unsafe { inner.as_mut().unwrap() };
let qsettings = QSettings::from_path(config_file);

assert_eq!(qsettings.value_bool("test_true"), false);
assert_eq!(qsettings.value_bool("test_false"), true);
Expand All @@ -177,7 +163,6 @@ fn test_qsettings_values() {
assert_eq!(qsettings.value_string("test_emoji"), "🦀");

drop(qsettings);
drop(inner);

drop(temp_dir);
assert!(!config_pathbuf.as_path().exists());
Expand Down

0 comments on commit bfa80db

Please sign in to comment.