diff --git a/src/gsiqt/qt5/QtCore/gsiDeclQCoreApplication.cc b/src/gsiqt/qt5/QtCore/gsiDeclQCoreApplication.cc index bcde7da5c..a4aeafa73 100644 --- a/src/gsiqt/qt5/QtCore/gsiDeclQCoreApplication.cc +++ b/src/gsiqt/qt5/QtCore/gsiDeclQCoreApplication.cc @@ -991,6 +991,27 @@ GSI_QTCORE_PUBLIC gsi::Class &qtdecl_QCoreApplication () { ret class QCoreApplication_Adaptor : public QCoreApplication, public qt_gsi::QtObjectBase { public: + static QCoreApplication *ctor_QCoreApplication_Adaptor_args(const std::vector &args) + { + // QCoreApplication needs static sources, so we give it some. + static char **argv = 0; + static std::vector args_copy; + static int argc = 0; + + if (argv != 0) { + throw tl::Exception(tl::to_string(QObject::tr("QCoreApplication cannot be instantiated twice"))); + } + argv = new char *[args.size ()]; + args_copy = args; + argc = int (args.size ()); + for (std::vector::const_iterator a = args_copy.begin (); a != args_copy.end (); ++a) { + argv[a - args_copy.begin ()] = (char *) a->c_str (); + } + + return new QCoreApplication_Adaptor (argc, argv); + } + + QCoreApplication_Adaptor (int &argc, char **argv) : QCoreApplication (argc, argv) { } virtual ~QCoreApplication_Adaptor(); @@ -1503,6 +1524,8 @@ static gsi::Methods methods_QCoreApplication_Adaptor () { } gsi::Class decl_QCoreApplication_Adaptor (qtdecl_QCoreApplication (), "QtCore", "QCoreApplication", + gsi::constructor("new", &QCoreApplication_Adaptor::ctor_QCoreApplication_Adaptor_args, gsi::arg ("argv"), "@brief Creates a new QCoreApplication object\n\n@param argv The command line arguments to pass to Qt") ++ methods_QCoreApplication_Adaptor (), "@qt\n@brief Binding of QCoreApplication"); diff --git a/src/gsiqt/qt5/QtGui/gsiDeclQGuiApplication.cc b/src/gsiqt/qt5/QtGui/gsiDeclQGuiApplication.cc index 758b05010..9e14f5a9e 100644 --- a/src/gsiqt/qt5/QtGui/gsiDeclQGuiApplication.cc +++ b/src/gsiqt/qt5/QtGui/gsiDeclQGuiApplication.cc @@ -53,12 +53,6 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g ret.write (QGuiApplication::staticMetaObject); } - static QGuiApplication *ctor_QGuiApplication() - { - static char *(dummy_argv[]) = { (char *)"undefined_application" }; - int argc = 1; - return new QGuiApplication (argc, dummy_argv); - } // double QGuiApplication::devicePixelRatio() @@ -902,8 +896,6 @@ static gsi::Methods methods_QGuiApplication () { gsi::Class &qtdecl_QCoreApplication (); qt_gsi::QtNativeClass decl_QGuiApplication (qtdecl_QCoreApplication (), "QtGui", "QGuiApplication_Native", - gsi::constructor("new_app", &ctor_QGuiApplication, "@brief Creates a new QGuiApplication object\n\nThis implementation is provided for test purposes only. It is not required usually to create a QGuiApplication object. Use the object provided by QGuiApplication::instance instead.") -+ methods_QGuiApplication (), "@hide\n@alias QGuiApplication"); @@ -915,6 +907,27 @@ GSI_QTGUI_PUBLIC gsi::Class &qtdecl_QGuiApplication () { return class QGuiApplication_Adaptor : public QGuiApplication, public qt_gsi::QtObjectBase { public: + static QGuiApplication *ctor_QGuiApplication_Adaptor_args(const std::vector &args) + { + // QGuiApplication needs static sources, so we give it some. + static char **argv = 0; + static std::vector args_copy; + static int argc = 0; + + if (argv != 0) { + throw tl::Exception(tl::to_string(QObject::tr("QGuiApplication cannot be instantiated twice"))); + } + argv = new char *[args.size ()]; + args_copy = args; + argc = int (args.size ()); + for (std::vector::const_iterator a = args_copy.begin (); a != args_copy.end (); ++a) { + argv[a - args_copy.begin ()] = (char *) a->c_str (); + } + + return new QGuiApplication_Adaptor (argc, argv); + } + + QGuiApplication_Adaptor (int &argc, char **argv) : QGuiApplication (argc, argv) { } virtual ~QGuiApplication_Adaptor(); @@ -1694,6 +1707,8 @@ static gsi::Methods methods_QGuiApplication_Adaptor () { } gsi::Class decl_QGuiApplication_Adaptor (qtdecl_QGuiApplication (), "QtGui", "QGuiApplication", + gsi::constructor("new", &QGuiApplication_Adaptor::ctor_QGuiApplication_Adaptor_args, gsi::arg ("argv"), "@brief Creates a new QGuiApplication object\n\n@param argv The command line arguments to pass to Qt") ++ methods_QGuiApplication_Adaptor (), "@qt\n@brief Binding of QGuiApplication"); diff --git a/src/gsiqt/qt5/QtWidgets/gsiDeclQApplication.cc b/src/gsiqt/qt5/QtWidgets/gsiDeclQApplication.cc index 9325c74d0..55d41eee7 100644 --- a/src/gsiqt/qt5/QtWidgets/gsiDeclQApplication.cc +++ b/src/gsiqt/qt5/QtWidgets/gsiDeclQApplication.cc @@ -53,12 +53,6 @@ static void _call_smo (const qt_gsi::GenericStaticMethod *, gsi::SerialArgs &, g ret.write (QApplication::staticMetaObject); } - static QApplication *ctor_QApplication() - { - static char *(dummy_argv[]) = { (char *)"undefined_application" }; - int argc = 1; - return new QApplication (argc, dummy_argv); - } // bool QApplication::autoSipEnabled() @@ -1158,8 +1152,6 @@ static gsi::Methods methods_QApplication () { gsi::Class &qtdecl_QGuiApplication (); qt_gsi::QtNativeClass decl_QApplication (qtdecl_QGuiApplication (), "QtWidgets", "QApplication_Native", - gsi::constructor("new_app", &ctor_QApplication, "@brief Creates a new QApplication object\n\nThis implementation is provided for test purposes only. It is not required usually to create a QApplication object. Use the object provided by QApplication::instance instead.") -+ methods_QApplication (), "@hide\n@alias QApplication"); @@ -1171,6 +1163,27 @@ GSI_QTWIDGETS_PUBLIC gsi::Class &qtdecl_QApplication () { return d class QApplication_Adaptor : public QApplication, public qt_gsi::QtObjectBase { public: + static QApplication *ctor_QApplication_Adaptor_args(const std::vector &args) + { + // QApplication needs static sources, so we give it some. + static char **argv = 0; + static std::vector args_copy; + static int argc = 0; + + if (argv != 0) { + throw tl::Exception(tl::to_string(QObject::tr("QApplication cannot be instantiated twice"))); + } + argv = new char *[args.size ()]; + args_copy = args; + argc = int (args.size ()); + for (std::vector::const_iterator a = args_copy.begin (); a != args_copy.end (); ++a) { + argv[a - args_copy.begin ()] = (char *) a->c_str (); + } + + return new QApplication_Adaptor (argc, argv); + } + + QApplication_Adaptor (int &argc, char **argv) : QApplication (argc, argv) { } virtual ~QApplication_Adaptor(); @@ -1978,6 +1991,8 @@ static gsi::Methods methods_QApplication_Adaptor () { } gsi::Class decl_QApplication_Adaptor (qtdecl_QApplication (), "QtWidgets", "QApplication", + gsi::constructor("new", &QApplication_Adaptor::ctor_QApplication_Adaptor_args, gsi::arg ("argv"), "@brief Creates a new QApplication object\n\n@param argv The command line arguments to pass to Qt") ++ methods_QApplication_Adaptor (), "@qt\n@brief Binding of QApplication"); diff --git a/src/lay/lay/layApplication.cc b/src/lay/lay/layApplication.cc index 556994445..5058823e0 100644 --- a/src/lay/lay/layApplication.cc +++ b/src/lay/lay/layApplication.cc @@ -1348,10 +1348,6 @@ GuiApplication::GuiApplication (int &argc, char **argv) #if QT_VERSION >= 0x040500 setAttribute (Qt::AA_DontShowIconsInMenus, false); #endif - - // only a GUI-enabled application runs an event loop and can have a deferred - // method scheduler therefore. - mp_dm_scheduler.reset (new tl::DeferredMethodScheduler ()); } GuiApplication::~GuiApplication () @@ -1533,8 +1529,8 @@ GuiApplication::process_events_impl (QEventLoop::ProcessEventsFlags flags, bool { if (mp_mw) { - if (silent) { - mp_dm_scheduler->enable (false); + if (silent && tl::DeferredMethodScheduler::instance ()) { + tl::DeferredMethodScheduler::instance ()->enable (false); } #if QT_VERSION < 0x050000 @@ -1549,8 +1545,8 @@ GuiApplication::process_events_impl (QEventLoop::ProcessEventsFlags flags, bool } mp_mw->enter_busy_mode (false); - if (silent) { - mp_dm_scheduler->enable (true); + if (silent && tl::DeferredMethodScheduler::instance ()) { + tl::DeferredMethodScheduler::instance ()->enable (true); } } diff --git a/src/lay/lay/layApplication.h b/src/lay/lay/layApplication.h index f02aae551..370b07424 100644 --- a/src/lay/lay/layApplication.h +++ b/src/lay/lay/layApplication.h @@ -48,11 +48,6 @@ namespace gtf class Recorder; } -namespace tl -{ - class DeferredMethodScheduler; -} - namespace lym { class MacroCollection; @@ -476,7 +471,6 @@ protected: private: MainWindow *mp_mw; gtf::Recorder *mp_recorder; - std::auto_ptr mp_dm_scheduler; }; /** diff --git a/src/lay/lay/layMainWindow.cc b/src/lay/lay/layMainWindow.cc index 6102aaadf..27261d341 100644 --- a/src/lay/lay/layMainWindow.cc +++ b/src/lay/lay/layMainWindow.cc @@ -461,6 +461,9 @@ MainWindow::MainWindow (QApplication *app, const char *name) m_busy (false), mp_app (app) { + // ensures the deferred method scheduler is present + tl::DeferredMethodScheduler::instance (); + setObjectName (QString::fromUtf8 (name)); if (mw_instance != 0) { diff --git a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc index eb77e6822..72fcf2ed3 100644 --- a/src/laybasic/laybasic/gsiDeclLayLayoutView.cc +++ b/src/laybasic/laybasic/gsiDeclLayLayoutView.cc @@ -23,6 +23,8 @@ #include "gsiDecl.h" #include "gsiSignals.h" +#include "gsiQtGuiExternals.h" +#include "gsiQtWidgetsExternals.h" // for Qt5 #include "rdb.h" #include "layLayoutView.h" #include "layDitherPattern.h" @@ -367,7 +369,7 @@ static lay::LayoutView *new_view () return new lay::LayoutView (0, false, 0); } -Class decl_LayoutView ("lay", "LayoutView", +Class decl_LayoutView (QT_EXTERNAL_BASE (QWidget) "lay", "LayoutView", gsi::constructor ("new", &new_view, "@brief Creates a standalone view\n" "\n" diff --git a/src/laybasic/laybasic/layLayoutView.cc b/src/laybasic/laybasic/layLayoutView.cc index fc06d5685..908224f07 100644 --- a/src/laybasic/laybasic/layLayoutView.cc +++ b/src/laybasic/laybasic/layLayoutView.cc @@ -255,6 +255,9 @@ LayoutView::LayoutView (db::Manager *manager, bool editable, lay::PluginRoot *ro m_annotation_shapes (manager), dm_prop_changed (this, &LayoutView::do_prop_changed) { + // ensures the deferred method scheduler is present + tl::DeferredMethodScheduler::instance (); + setObjectName (QString::fromUtf8 (name)); init (manager, root, parent); } @@ -267,6 +270,9 @@ LayoutView::LayoutView (lay::LayoutView *source, db::Manager *manager, bool edit m_annotation_shapes (manager), dm_prop_changed (this, &LayoutView::do_prop_changed) { + // ensures the deferred method scheduler is present + tl::DeferredMethodScheduler::instance (); + setObjectName (QString::fromUtf8 (name)); m_annotation_shapes = source->m_annotation_shapes; diff --git a/src/pya/pya/pya.cc b/src/pya/pya/pya.cc index 99a84e55f..6b104add0 100644 --- a/src/pya/pya/pya.cc +++ b/src/pya/pya/pya.cc @@ -2223,6 +2223,12 @@ PythonModule::PythonModule () PythonModule::~PythonModule () { PYAObjectBase::clear_callbacks_cache (); + + // the Python objects were probably deleted by Python itself as it exited - + // don't try to delete them again. + mp_module.release (); + mp_base_class.release (); + delete_module (); } diff --git a/src/tl/tl/tlDeferredExecution.cc b/src/tl/tl/tlDeferredExecution.cc index f238eecf4..f373286e8 100644 --- a/src/tl/tl/tlDeferredExecution.cc +++ b/src/tl/tl/tlDeferredExecution.cc @@ -34,8 +34,8 @@ namespace tl static DeferredMethodScheduler *s_inst = 0; -DeferredMethodScheduler::DeferredMethodScheduler () - : QObject (0), +DeferredMethodScheduler::DeferredMethodScheduler (QObject *parent) + : QObject (parent), m_disabled (0), m_scheduled (false) { connect (&m_timer, SIGNAL (timeout ()), this, SLOT (timer ())); @@ -60,8 +60,9 @@ DeferredMethodScheduler::~DeferredMethodScheduler () DeferredMethodScheduler * DeferredMethodScheduler::instance () { - // NOTE: this is not locked intentionally. The instance is shut down once in the application shortly before it - // will terminate and it is created initially before any threads start. + if (! s_inst && qApp) { + new DeferredMethodScheduler (qApp); + } return s_inst; } diff --git a/src/tl/tl/tlDeferredExecution.h b/src/tl/tl/tlDeferredExecution.h index 08fc34925..092231e1b 100644 --- a/src/tl/tl/tlDeferredExecution.h +++ b/src/tl/tl/tlDeferredExecution.h @@ -71,16 +71,6 @@ class TL_PUBLIC DeferredMethodScheduler { Q_OBJECT public: - /** - * @brief Constructor - */ - DeferredMethodScheduler (); - - /** - * @brief Destructor - */ - ~DeferredMethodScheduler (); - /** * @brief The singleton instance of the scheduler */ @@ -129,6 +119,16 @@ private slots: void timer (); private: + /** + * @brief Constructor + */ + DeferredMethodScheduler (QObject *parent); + + /** + * @brief Destructor + */ + ~DeferredMethodScheduler (); + int m_disabled; bool m_scheduled; std::list m_methods;