diff --git a/Cargo.toml b/Cargo.toml index 634317e..5a99c62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,5 +20,8 @@ qttypes = "0.2" cpp_build = "0.5" semver = "1.0" +[dev-dependencies] +lazy_static = "1.4" + [package.metadata.docs.rs] dependencies = ["qtbase5-dev", "qtdeclarative5-dev", "libqt5svg5-dev", "qtquickcontrols2-5-dev", "qml-module-org-kde-kirigami2", "kirigami2-dev", "libkf5i18n-dev", "gettext", "libkf5coreaddons-dev", "qml-module-qtquick-layouts"] diff --git a/src/klocalizedcontext.rs b/src/klocalizedcontext.rs new file mode 100644 index 0000000..7b9d37a --- /dev/null +++ b/src/klocalizedcontext.rs @@ -0,0 +1,55 @@ +use cpp::{cpp, cpp_class}; +use qmetaobject::prelude::*; +use std::ffi::c_void; + +cpp! {{ + #include + #include + #include + #include + + struct KLocalizedContextHolder { + std::unique_ptr klocalized; + + KLocalizedContextHolder(QObject *parent) : klocalized(new KLocalizedContext(parent)) {} + }; +}} + +cpp_class!( + /// Struct representing KLocalizedContext. Mainly used with QML. + pub unsafe struct KLocalizedContext as "KLocalizedContextHolder" +); + +impl KLocalizedContext { + /// Initialize KLocalizedContext from Engine. + pub fn init_from_engine(engine: &QmlEngine) -> Self { + let engine_ptr = engine.cpp_ptr(); + cpp!(unsafe [engine_ptr as "QQmlEngine*"] -> KLocalizedContext as "KLocalizedContextHolder" { + auto klocalized = new KLocalizedContext(engine_ptr); + auto klocalizedholder = KLocalizedContextHolder(klocalized); + engine_ptr->rootContext()->setContextObject(klocalized); + return klocalizedholder; + }) + } + + /// Returns a pointer to the C++ object. The pointer is of the type `KLocalizedContext *` in C++. + pub fn cpp_ptr(&self) -> *mut c_void { + cpp!(unsafe [self as "KLocalizedContextHolder *"] -> *mut c_void as "KLocalizedContext *" { + return self->klocalized.get(); + }) + } + + /// Set Translation Domain for current KLocalizedContext. + pub fn set_translation_domain(&mut self, domain: QString) { + cpp!(unsafe [self as "KLocalizedContextHolder *", domain as "QString"] { + self->klocalized->setTranslationDomain(domain); + }) + } + + /// Retrns the current Translation Domain. + pub fn translation_domain(&self) -> QString { + cpp!(unsafe [self as "KLocalizedContextHolder *"] -> QString as "QString" { + return self->klocalized->translationDomain(); + }) + } +} diff --git a/src/lib.rs b/src/lib.rs index 283d530..17845be 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,11 @@ //! # KI18n-rs //! KI18n is a cross-platform internationalization framework used by KDE applications. This crate is meant to allow using KI18n with //! Rust and [qmetaobject-rs](https://github.com/woboq/qmetaobject-rs) crate. +//! +//! # Custom Location for KF5I18n +//! The crate searches from KF5I18n using either the environment variables (KF5_I18n_INCLUDE_PATH and KF5_I18n_LIBRARY_PATH) if they are set or just +//! searches at /usr/include /usr/library +//! //! # Example //! ```ignore //! use cstr::cstr; @@ -39,99 +44,6 @@ //! engine.exec(); //! } //! ``` -use cpp::{cpp, cpp_class}; -use qmetaobject::prelude::*; -use std::ffi::c_void; -cpp! {{ - #include - #include - #include - #include - - struct KLocalizedContextHolder { - std::unique_ptr klocalized; - - KLocalizedContextHolder(QObject *parent) : klocalized(new KLocalizedContext(parent)) {} - }; -}} - -cpp_class!( - /// Struct representing KLocalizedContext. Mainly used with QML. - pub unsafe struct KLocalizedContext as "KLocalizedContextHolder" -); - -impl KLocalizedContext { - /// Initialize KLocalizedContext from Engine. - /// ```rust - /// use qmetaobject::prelude::*; - /// use ki18n_rs::KLocalizedContext; - /// - /// let mut engine = QmlEngine::new(); - /// let context = KLocalizedContext::init_from_engine(&engine); - /// ``` - pub fn init_from_engine(engine: &QmlEngine) -> Self { - let engine_ptr = engine.cpp_ptr(); - cpp!(unsafe [engine_ptr as "QQmlEngine*"] -> KLocalizedContext as "KLocalizedContextHolder" { - auto klocalized = new KLocalizedContext(engine_ptr); - auto klocalizedholder = KLocalizedContextHolder(klocalized); - engine_ptr->rootContext()->setContextObject(klocalized); - return klocalizedholder; - }) - } - - /// Returns a pointer to the C++ object. The pointer is of the type `KLocalizedContext *` in C++. - /// ```rust - /// use qmetaobject::prelude::*; - /// use ki18n_rs::KLocalizedContext; - /// - /// let mut engine = QmlEngine::new(); - /// let context = KLocalizedContext::init_from_engine(&engine); - /// - /// let context_ptr = context.cpp_ptr(); - /// ``` - pub fn cpp_ptr(&self) -> *mut c_void { - cpp!(unsafe [self as "KLocalizedContextHolder *"] -> *mut c_void as "KLocalizedContext *" { - return self->klocalized.get(); - }) - } - - /// Set Translation Domain for current KLocalizedContext. - /// ```rust - /// use qmetaobject::prelude::*; - /// use ki18n_rs::KLocalizedContext; - /// - /// let mut engine = QmlEngine::new(); - /// let mut context = KLocalizedContext::init_from_engine(&engine); - /// - /// const TRANSLATION_DOMAIN: &str = "Test Domain"; - /// context.set_translation_domain(TRANSLATION_DOMAIN.into()); - /// - /// let domain = context.translation_domain(); - /// - /// assert_eq!(domain, QString::from(TRANSLATION_DOMAIN)); - /// ``` - pub fn set_translation_domain(&mut self, domain: QString) { - cpp!(unsafe [self as "KLocalizedContextHolder *", domain as "QString"] { - self->klocalized->setTranslationDomain(domain); - }) - } - - /// Retrns the current Translation Domain. - /// ```rust - /// use qmetaobject::prelude::*; - /// use ki18n_rs::KLocalizedContext; - /// - /// let mut engine = QmlEngine::new(); - /// let mut context = KLocalizedContext::init_from_engine(&engine); - /// - /// let domain = context.translation_domain(); - /// - /// assert_eq!(domain, QString::from("")); - /// ``` - pub fn translation_domain(&self) -> QString { - cpp!(unsafe [self as "KLocalizedContextHolder *"] -> QString as "QString" { - return self->klocalized->translationDomain(); - }) - } -} +mod klocalizedcontext; +pub use klocalizedcontext::KLocalizedContext; diff --git a/tests/common.rs b/tests/common.rs new file mode 100644 index 0000000..46910dd --- /dev/null +++ b/tests/common.rs @@ -0,0 +1,12 @@ +use lazy_static::lazy_static; +use std::sync::Mutex; + +lazy_static! { + pub static ref TEST_MUTEX: Mutex<()> = Mutex::new(()); +} + +/// There can only be one thread running at the time with a QQuickEngine +/// (in principle, everything should be in the same main thread) +pub fn lock_for_test() -> std::sync::MutexGuard<'static, ()> { + TEST_MUTEX.lock().unwrap_or_else(|e| e.into_inner()) +} diff --git a/tests/klocalizedcontext_tests.rs b/tests/klocalizedcontext_tests.rs new file mode 100644 index 0000000..7c4ebec --- /dev/null +++ b/tests/klocalizedcontext_tests.rs @@ -0,0 +1,37 @@ +use ki18n_rs::KLocalizedContext; +use qmetaobject::prelude::*; +mod common; + +#[test] +fn init_engine() { + let _lock = common::lock_for_test(); + + let engine = QmlEngine::new(); + KLocalizedContext::init_from_engine(&engine); +} + +#[test] +fn cpp_ptr() { + let _lock = common::lock_for_test(); + + let engine = QmlEngine::new(); + let context = KLocalizedContext::init_from_engine(&engine); + + let context_ptr = context.cpp_ptr(); + assert_ne!(std::ptr::null(), context_ptr); +} + +#[test] +fn translation_domain() { + let _lock = common::lock_for_test(); + + let engine = QmlEngine::new(); + let mut context = KLocalizedContext::init_from_engine(&engine); + + const TRANSLATION_DOMAIN: &str = "Test Domain"; + context.set_translation_domain(TRANSLATION_DOMAIN.into()); + + let domain = context.translation_domain(); + + assert_eq!(domain, QString::from(TRANSLATION_DOMAIN)); +} diff --git a/tests/tests.rs b/tests/tests.rs deleted file mode 100644 index 344f078..0000000 --- a/tests/tests.rs +++ /dev/null @@ -1 +0,0 @@ -use ki18n_rs::*;