diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/QGlib/emitimpl.h | 67 | ||||
-rw-r--r-- | src/QGlib/signal.cpp | 6 | ||||
-rw-r--r-- | src/QGlib/value.cpp | 33 | ||||
-rw-r--r-- | src/QGlib/value.h | 52 |
4 files changed, 91 insertions, 67 deletions
diff --git a/src/QGlib/emitimpl.h b/src/QGlib/emitimpl.h index 3d2529f..0d295ab 100644 --- a/src/QGlib/emitimpl.h +++ b/src/QGlib/emitimpl.h @@ -52,13 +52,12 @@ inline QList<Value> packArguments() template <typename Arg1, typename... Args> QList<Value> packArguments(Arg1 && a1, Args&&... args) { - typedef typename boost::add_const< - typename boost::add_reference<Arg1>::type - >::type ConstArg1Ref; - QList<Value> result = packArguments(std::forward<Args>(args)...); + Value v; + v.init<Arg1>(); + ValueImpl<Arg1>::set(v, a1); //prepend, since we are packing from the last to the first argument - result.prepend(Value(static_cast<ConstArg1Ref>(a1))); + result.prepend(v); return result; } @@ -70,14 +69,12 @@ struct EmitImpl<R (Args...)> { static inline R emit(void *instance, const char *detailedSignal, Args&&... args) { - Value && returnValue = Signal::emit(instance, detailedSignal, - packArguments(std::forward<Args>(args)...)); - try { + Value && returnValue = Signal::emit(instance, detailedSignal, + packArguments(std::forward<Args>(args)...)); return ValueImpl<R>::get(returnValue); - } catch(const std::logic_error &) { - qCritical() << "Error during emission of signal" << detailedSignal - << "The returned value from emit is of different type than the one requested"; + } catch(const std::exception & e) { + qCritical() << "Error during emission of signal" << detailedSignal << ":" << e.what(); return R(); } } @@ -88,11 +85,15 @@ struct EmitImpl<void (Args...)> { static inline void emit(void *instance, const char *detailedSignal, Args&&... args) { - Value && returnValue = Signal::emit(instance, detailedSignal, - packArguments(std::forward<Args>(args)...)); - - if (returnValue.isValid()) { - qWarning() << "Ignoring return value from emission of signal" << detailedSignal; + try { + Value && returnValue = Signal::emit(instance, detailedSignal, + packArguments(std::forward<Args>(args)...)); + + if (returnValue.isValid()) { + qWarning() << "Ignoring return value from emission of signal" << detailedSignal; + } + } catch(const std::exception & e) { + qCritical() << "Error during emission of signal" << detailedSignal << ":" << e.what(); } } }; @@ -161,7 +162,12 @@ namespace Private { //BEGIN ******** boostpp EmitImpl ******** # define QGLIB_SIGNAL_IMPL_PACK_ARGS_STEP(z, n, list) \ - list.append(Value(static_cast< typename boost::add_const< typename boost::add_reference<A ##n>::type >::type >(a ##n))); + { \ + Value v; \ + v.init<A##n>(); \ + ValueImpl<A##n>::set(v, a##n); \ + list.append(v); \ + } # define QGLIB_SIGNAL_IMPL_PACK_ARGS(list) \ BOOST_PP_REPEAT(QGLIB_SIGNAL_IMPL_NUM_ARGS, QGLIB_SIGNAL_IMPL_PACK_ARGS_STEP, list) @@ -173,15 +179,13 @@ struct EmitImpl<R (QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS)> static inline R emit(void *instance, const char *detailedSignal QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS) { - QList<Value> values; - QGLIB_SIGNAL_IMPL_PACK_ARGS(values) - Value returnValue = Signal::emit(instance, detailedSignal, values); - try { + QList<Value> values; + QGLIB_SIGNAL_IMPL_PACK_ARGS(values) + Value returnValue = Signal::emit(instance, detailedSignal, values); return ValueImpl<R>::get(returnValue); - } catch(const std::logic_error &) { - qCritical() << "Error during emission of signal" << detailedSignal - << "The returned value from emit is of different type than the one requested"; + } catch(const std::exception & e) { + qCritical() << "Error during emission of signal" << detailedSignal << ":" << e.what(); return R(); } } @@ -193,12 +197,15 @@ struct EmitImpl<void (QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS)> static inline void emit(void *instance, const char *detailedSignal QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS) { - QList<Value> values; - QGLIB_SIGNAL_IMPL_PACK_ARGS(values) - Value returnValue = Signal::emit(instance, detailedSignal, values); - - if (returnValue.isValid()) { - qWarning() << "Ignoring return value from emission of signal" << detailedSignal; + try { + QList<Value> values; + QGLIB_SIGNAL_IMPL_PACK_ARGS(values) + Value returnValue = Signal::emit(instance, detailedSignal, values); + if (returnValue.isValid()) { + qWarning() << "Ignoring return value from emission of signal" << detailedSignal; + } + } catch(const std::exception & e) { + qCritical() << "Error during emission of signal" << detailedSignal << ":" << e.what(); } } }; diff --git a/src/QGlib/signal.cpp b/src/QGlib/signal.cpp index 684d810..06da8f8 100644 --- a/src/QGlib/signal.cpp +++ b/src/QGlib/signal.cpp @@ -266,7 +266,7 @@ static void c_marshaller(GClosure *closure, GValue *returnValue, uint paramValue try { SharedValue result(returnValue); cdata->marshaller(result, params); - } catch (const std::logic_error & e) { + } catch (const std::exception & e) { QString signalName; if (hint != NULL) { GSignalInvocationHint *ihint = static_cast<GSignalInvocationHint*>(hint); @@ -293,13 +293,13 @@ static void c_marshaller(GClosure *closure, GValue *returnValue, uint paramValue QString msg; try { //dynamic_cast will throw an std::bad_cast if it fails - dynamic_cast<const ValueBase::InvalidTypeException &>(e); + dynamic_cast<const InvalidTypeException &>(e); //cast succeded, e is indeed an InvalidTypeException msg = QLatin1String("One or more of the arguments of the signal are of different " "type than the type that the closure expects"); } catch (...) { try { - dynamic_cast<const ValueBase::InvalidValueException &>(e); + dynamic_cast<const InvalidValueException &>(e); //cast succeded, e is indeed an InvalidValueException //this is most likely to happen because the signal returns void //but the closure returns something non-void. check this first. diff --git a/src/QGlib/value.cpp b/src/QGlib/value.cpp index e353ca0..9178db9 100644 --- a/src/QGlib/value.cpp +++ b/src/QGlib/value.cpp @@ -158,58 +158,53 @@ void ValueBase::registerValueVTable(Type type, const ValueVTable & vtable) void ValueBase::getData(Type dataType, void *data) const { if (!isValid()) { - throw InvalidValueException(); + throw Private::InvalidValueException(); } else if (g_value_type_compatible(type(), dataType)) { ValueVTable vtable = s_dispatcher()->getVTable(dataType); if (vtable.get != NULL) { vtable.get(*this, data); } else { - throw std::logic_error("Unable to handle the given type. Type is not registered"); + throw Private::UnregisteredTypeException(dataType.name().toStdString()); } } else if (dataType.isValueType() && g_value_type_transformable(type(), dataType)) { Value v; v.init(dataType); if (!g_value_transform(m_value, v.m_value)) { - throw InvalidTypeException(); + throw Private::TransformationFailedException(type().name().toStdString(), + dataType.name().toStdString()); } - try { - v.getData(dataType, data); - } catch (const InvalidTypeException &) { - Q_ASSERT(false); //This must never happen - } + v.getData(dataType, data); } else { - throw InvalidTypeException(); + throw Private::InvalidTypeException(dataType.name().toStdString(), + type().name().toStdString()); } } void ValueBase::setData(Type dataType, const void *data) { if (!isValid()) { - throw InvalidValueException(); + throw Private::InvalidValueException(); } else if (g_value_type_compatible(dataType, type())) { ValueVTable vtable = s_dispatcher()->getVTable(dataType); if (vtable.set != NULL) { vtable.set(*this, data); } else { - throw std::logic_error("Unable to handle the given type. Type is not registered"); + throw Private::UnregisteredTypeException(dataType.name().toStdString()); } } else if (dataType.isValueType() && g_value_type_transformable(dataType, type())) { Value v; v.init(dataType); - - try { - v.setData(dataType, data); - } catch (const InvalidTypeException &) { - Q_ASSERT(false); //This must never happen - } + v.setData(dataType, data); if (!g_value_transform(v.m_value, m_value)) { - throw InvalidTypeException(); + throw Private::TransformationFailedException(dataType.name().toStdString(), + type().name().toStdString()); } } else { - throw InvalidTypeException(); + throw Private::InvalidTypeException(dataType.name().toStdString(), + type().name().toStdString()); } } diff --git a/src/QGlib/value.h b/src/QGlib/value.h index 3ad59c7..014225b 100644 --- a/src/QGlib/value.h +++ b/src/QGlib/value.h @@ -56,21 +56,6 @@ struct ValueVTable class ValueBase { public: - class InvalidValueException : public std::logic_error - { - public: - inline InvalidValueException() - : std::logic_error("This ValueBase instance has not been initialized") {} - }; - - class InvalidTypeException : public std::logic_error - { - public: - inline InvalidTypeException() - : std::logic_error("This ValueBase instance has been initialized to hold a different " - "type of data than the one that you are trying to access") {} - }; - /*! \returns whether this ValueBase instance wraps a valid GValue instance or not */ bool isValid() const; @@ -380,6 +365,43 @@ struct ValueImpl<QString> } }; +// -- Exceptions thrown from getData/setData -- + +namespace Private { + +class InvalidValueException : public std::logic_error +{ +public: + inline InvalidValueException() + : std::logic_error("This Value instance has not been initialized") {} +}; + +class InvalidTypeException : public std::logic_error +{ +public: + inline InvalidTypeException(const std::string & dataType, const std::string & valueType) + : std::logic_error("Unable to handle value type \"" + dataType + + "\". This Value instance has been initialized to hold values of type \"" + + valueType + "\" and no conversion is possible") {} +}; + +class UnregisteredTypeException : public std::logic_error +{ +public: + inline UnregisteredTypeException(const std::string & typeName) + : std::logic_error("Unable to handle unregistered type \"" + typeName + "\"") {} +}; + +class TransformationFailedException : public std::runtime_error +{ +public: + inline TransformationFailedException(const std::string & srcTypeName, + const std::string & destTypeName) + : std::runtime_error("Failed to transform value from type \"" + + srcTypeName + "\" to type \"" + destTypeName + "\"") {} +}; + +} //namespace Private } //namespace QGlib /*! \relates QGlib::ValueBase */ |