(C++) Wt with Qt under Qt Creator under Ubuntu
January 25, 2018 · View on GitHub
(C++) 


Wt with Qt under Qt Creator under Ubuntu
Wt with Qt under Qt Creator under Ubuntu does not compile.
A more modified version of the code can be found at Wt with Qt under Qt Creator under Lubuntu, which does compile, but results in a runtime error.
Technical facts
Operating system(s) or programming environment(s)
Ubuntu 10.10 (maverick)
Qt Creator 2.0.0
- G++ 4.4.5
Libraries used:
Qt project file: CppWtWithQt.pro
#------------------------------------------------- # # Project created by QtCreator 2010-12-29T21:57:10 # #------------------------------------------------- QT += core QT -= gui INCLUDEPATH += lib LIBS += -lwt -lwthttp QMAKE_CXXFLAGS += -DNDEBUG TARGET = CppWtWithQt CONFIG += console CONFIG -= app_bundle TEMPLATE = app SOURCES += QtObject.C \ hello.C \ lib/WQApplication.C \ lib/DispatchThread.C HEADERS += \ QtObject.h \ HelloApplication.h \ lib/DispatchThread.h
HelloApplication.h
// This may look like C code, but it's really -*- C++ -*- /* * Copyright 2008 Emweb bvba, Heverlee, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef HELLO_APPLICATION_H_ #define HELLO_APPLICATION_H_ #include "WQApplication" class QtObject; class QString; using namespace Wt; namespace Wt { class WLineEdit; class WText; } /*! \class HelloApplication * \brief The 'hello' application modified to use QtCore * * A sample application that uses objects from the QtCore library. */ class HelloApplication : public WQApplication { public: HelloApplication(const WEnvironment& env); void doGreet(const QString&); virtual void create(); virtual void destroy(); private: WLineEdit *nameEdit_; WText *greeting_; QtObject *qtSender_, *qtReceiver_; void propagateGreet(); }; #endif // HELLO_APPLICATION_H_
QtObject.c
/* * Copyright 2008 Emweb bvba, Heverlee, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include "HelloApplication.h" #include "QtObject.h" QtObject::QtObject(HelloApplication *wt, QObject *parent) : QObject(parent), wt_(wt) { } void QtObject::passGreet(const QString& name) { emit greet(name); } void QtObject::doGreet(const QString& name) { wt_->doGreet(name); }
QtObject.h
// This may look like C code, but it's really -*- C++ -*- /* * Copyright 2008 Emweb bvba, Heverlee, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef QTOBJECT_H_ #define QTOBJECT_H_ #ifdef SLOT # undef SLOT # undef signals # undef slots #endif #include <QThread> class HelloApplication; /*! \class QtObject * \brief A simple Qt object with sample signal and slot. * * This simple object class demonstrates that the Qt signal/slot * mechanism may be used alonglisde Wt's signal/slot mechanism. */ class QtObject : public QObject { Q_OBJECT; public: QtObject(HelloApplication *wt_, QObject *parent = 0); void passGreet(const QString&); signals: void greet(const QString&); public slots: void doGreet(const QString&); private: HelloApplication *wt_; }; #endif // QTOBJECT_H_
hello.c
/* * Copyright 2008 Emweb bvba, Heverlee, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include <iostream> #include <Wt/WBreak> #include <Wt/WContainerWidget> #include <Wt/WLineEdit> #include <Wt/WPushButton> #include <Wt/WText> #include "HelloApplication.h" #include "QtObject.h" using namespace Wt; HelloApplication::HelloApplication(const WEnvironment& env) : WQApplication(env) { /* * Note: do not create any Qt objects from here. Initialize your * application from within the virtual create() method. */ } void HelloApplication::create() { setTitle("CppWtWithQt"); root()->addWidget(new WText("Your name, please ? ")); nameEdit_ = new WLineEdit(root()); nameEdit_->setFocus(); WPushButton *b = new WPushButton("Greet me.", root()); b->setMargin(5, Left); root()->addWidget(new WBreak()); greeting_ = new WText(root()); b->clicked().connect(this, &HelloApplication::propagateGreet); nameEdit_->enterPressed().connect(this, &HelloApplication::propagateGreet); qtSender_ = new QtObject(this); qtReceiver_ = new QtObject(this); QObject::connect(qtSender_, SIGNAL(greet(const QString&)), qtReceiver_, SLOT(doGreet(const QString&))); } void HelloApplication::destroy() { /* * Note: Delete any Qt object from here. */ delete qtSender_; delete qtReceiver_; } void HelloApplication::propagateGreet() { qtSender_->passGreet(toQString(nameEdit_->text())); } void HelloApplication::doGreet(const QString& qname) { greeting_->setText("Hello there, " + toWString(qname)); } WApplication *createApplication(const WEnvironment& env) { return new HelloApplication(env); } int main(int argc, char **argv) { return WRun(argc, argv, &createApplication); }
lib/DispatchThread.c
/* * Copyright 2008 Emweb bvba, Kessel-Lo, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include "WQApplication" #include "DispatchThread.h" namespace Wt { DispatchObject::DispatchObject(DispatchThread *thread) : thread_(thread) { connect(this, SIGNAL(doEvent()), this, SLOT(onEvent())); } void DispatchObject::propagateEvent() { emit doEvent(); } void DispatchObject::onEvent() { thread_->doEvent(); } DispatchThread::DispatchThread(WQApplication *app, bool withEventLoop) : QThread(), app_(app), qtEventLoop_(withEventLoop), dispatchObject_(0), event_(0), done_(false), newEvent_(false) { } void DispatchThread::run() { app_->attachThread(); app_->create(); if (qtEventLoop_) dispatchObject_ = new DispatchObject(this); signalDone(); if (qtEventLoop_) exec(); else myExec(); delete dispatchObject_; signalDone(); } void DispatchThread::myExec() { boost::mutex::scoped_lock lock(newEventMutex_); for (;;) { if (!newEvent_) newEventCondition_.wait(lock); if (doEvent()) return; newEvent_ = false; } } void DispatchThread::myPropagateEvent() { boost::mutex::scoped_lock lock(newEventMutex_); newEvent_ = true; newEventCondition_.notify_one(); } void DispatchThread::signalDone() { boost::mutex::scoped_lock lock(doneMutex_); done_ = true; doneCondition_.notify_one(); } void DispatchThread::waitDone() { boost::mutex::scoped_lock lock(doneMutex_); if (done_) return; else doneCondition_.wait(lock); } void DispatchThread::notify(const WEvent& event) { event_ = &event; done_ = false; if (dispatchObject_) dispatchObject_->propagateEvent(); else myPropagateEvent(); waitDone(); } void DispatchThread::destroy() { event_ = 0; done_ = false; if (dispatchObject_) dispatchObject_->propagateEvent(); else myPropagateEvent(); waitDone(); wait(); } bool DispatchThread::doEvent() { if (event_) { app_->realNotify(*event_); signalDone(); return false; } else { app_->destroy(); if (qtEventLoop_) QThread::exit(); return true; } } }
lib/DispatchThread.h
// This may look like C code, but it's really -*- C++ -*- /* * Copyright 2008 Emweb bvba, Kessel-Lo, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef DISPATCH_THREAD_H_ #define DISPATCH_THREAD_H_ #include <QThread> #include <boost/thread.hpp> #include <boost/thread/condition.hpp> namespace Wt { class WQApplication; class WEvent; class DispatchThread; /* * Help object used to dispatch an event into a Qt event loop. */ class DispatchObject : public QObject { Q_OBJECT; public: DispatchObject(DispatchThread *thread); void propagateEvent(); signals: void doEvent(); private slots: void onEvent(); private: DispatchThread *thread_; }; /* * Thread in which all interaction with Qt objects is done. * * If constructed <i>withEventLoop</i>, then QThread::exec() is * called, starting a new Qt event loop, and signal/slot events can be * delivered within the event loop handling. Otherwise, plain thread * synchronization is implemented. */ class DispatchThread : public QThread { public: DispatchThread(WQApplication *app, bool withEventLoop); virtual void run(); void notify(const WEvent& event); void destroy(); void waitDone(); private: WQApplication *app_; bool qtEventLoop_; DispatchObject *dispatchObject_; const WEvent *event_; boost::mutex doneMutex_; bool done_; boost::condition doneCondition_; boost::mutex newEventMutex_; bool newEvent_; boost::condition newEventCondition_; bool doEvent(); void signalDone(); void myExec(); void myPropagateEvent(); friend class DispatchObject; }; } #endif // DISPATCH_THREAD_H_
lib/WQApplication.c
/* * Copyright 2008 Emweb bvba, Kessel-Lo, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include <iostream> #include <boost/thread/condition.hpp> #include "WQApplication" #include "DispatchThread.h" namespace { } namespace Wt { WQApplication::WQApplication(const WEnvironment& env, bool withEventLoop) : WApplication(env), withEventLoop_(withEventLoop), thread_(0) { } void WQApplication::initialize() { if (thread_) return; thread_ = new DispatchThread(this, withEventLoop_); thread_->start(); thread_->waitDone(); } void WQApplication::finalize() { if (!thread_) return; thread_->destroy(); delete thread_; thread_ = 0; } void WQApplication::notify(const WEvent& e) { thread_->notify(e); } void WQApplication::realNotify(const WEvent& e) { WApplication::notify(e); } WString toWString(const QString& s) { return WString::fromUTF8((const char *)s.toUtf8()); } QString toQString(const WString& s) { return QString::fromUtf8(s.toUTF8().c_str()); } }
lib/WQApplication.h
// This may look like C code, but it's really -*- C++ -*- /* * Copyright 2008 Emweb bvba, Kessel-Lo, Belgium. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, * copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following * conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #ifndef WQAPPLICATION_H_ #define WQAPPLICATION_H_ #include <Wt/WApplication> #include <boost/thread.hpp> /*! \file WQApplication */ class QString; namespace Wt { class DispatchThread; /*! \class WQApplication WQApplication WQApplication * \brief An application class that provides interopability between * Wt and Qt. * * This class provides interopability between the Wt's multi threading * model and Qt's threading requirements for QObject. This is needed * because Qt's object model, which defines a hierarchy of QObjects, * requires that every QObject in the hierarchy is created from within * the same thread. In addition, Qt's signal/slot system is * thread-aware and behaves very differently when a signal is emitted * from within a different thread than the thread in which the * receiver object lives. * * Wt on the other hand does not guarantee that every event is * dispatched within the same thread. This is a side effect of the * fact that Wt uses thread pools in combination with asynchronous I/O * to be able to serve multiple connections simultaneously without * requiring a high number of threads. * * Therefore, you cannot manipulate a QObject hierarchy, or propagate * events using Qt's signal/slot system, in a multi-threaded Wt * application server, since this is likely to violate Qt's * thread/object assumptions, without taking precautions (as are * implemented in this application class). * * This class spawns a QThread that is dedicated to a single * application instance, and used for event handling, after your * application is constructed. You should not create any Qt objects * from the constructor, but rather from the create() method, which * runs within the context of this thread. Likewise, you should not * destroy Qt objects from the application destructor, but from the * destroy() method, which also runs in this thread. * * You may enable a Qt event loop in this QThread, by setting the * option in the constructor. In this way, you can use QTcpSocket and * other Qt classes which rely on the presence of an event loop. Note * that Qt requires that you instantiate a QApplication object before * you can use a Qt event loop (only one is needed per process, so it * may be shared between multiple Wt sessions). You need to do this * yourself, and a convenient location could be within your main() * function. */ class WQApplication : public WApplication { public: /*! \brief Constructor. * * Create a new application with Qt threading support. * * Set <i>enableQtEventLoop</i> if you wish to enable a Qt event * loop within the thread context, e.g. when you wish to use certain * non-GUI classes that require the presence of an event loop (such * as QTimer, QTcpSocket, ...). * * Note: you should not create Qt objects from within the * constructor. Instead, reimplement create(), which is called after * construction, from within the QThread. */ WQApplication(const WEnvironment& env, bool enableQtEventLoop = false); protected: /*! \brief Initialize Qt objects in your application within the * QThread context. * * Reimplement this method to construct your Wt widget and Qt object * hierarchy within the context of the dedicatd QThread. * * This method is called from within the library after your * application is created. */ virtual void create() = 0; /*! \brief Finalize your application within the QThread context. * * Reimplement this method to safely destroy Qt object hierarchy. * * This method is called from within the library before your * application is deleted. */ virtual void destroy() = 0; /*! \brief Notify an event to the application within the QThread * context. * * This method is the equivalent of WApplication::notify(), but runs * inside the QThread context. The default implementation simply * calls WApplication::notify(). */ virtual void realNotify(const WEvent& e); virtual void notify(const WEvent& e); virtual void initialize(); virtual void finalize(); private: bool withEventLoop_; DispatchThread *thread_; friend class DispatchThread; }; /*! \brief Conversion function from QString to WString * * Lossless conversion between these two unicode string classes. */ extern WString toWString(const QString& s); /*! \brief Conversion function from WString to QString * * Lossless conversion between these two unicode string classes. */ extern QString toQString(const WString& s); } #endif // WQAPPLICATION_H_