Software Engineer and Scout Leader in Yorkshire, UK
These are the steps I went through to build Qt 4.8 for Embedded Linux for the Raspberry Pi.
#include <iostream>Once you have a cross compiler working, edit your ~/.bash_profile file and add the directory containing the tools to your PATH.
int main(int, char**)
{
float a = 2.0f * 2.0f;
std::cout << "Test " << a << std::endl;
return 0;
}
export CC=`/bin/which arm-unknown-linux-gnueabi-gcc`
export AR=`/bin/which arm-unknown-linux-gnueabi-ar`
export RANLIB=`/bin/which arm-unknown-linux-gnueabi-ranlib`
cd zlib-1.2.7
./configure --prefix=/opt/raspi
make
sudo make install
cd openssl-1.0.1e
./Configure linux-elf zlib -L/opt/raspi/lib -I/opt/raspi/include --prefix=/opt/raspi no-asm
make
sudo make install
./configure -embedded arm -qt-freetype -prefix /opt/raspi -xplatform qws/linux-arm-gnueabi-g++ -I/opt/raspi/include -L/opt/raspi/lib -no-cups -qt-zlib -qt-libtiff -qt-libpng -qt-libmng -qt-libjpeg -no-javascript-jit -no-qt3support -qt-gfx-linuxfb -qt-gfx-transformed -plugin-gfx-vnc -qt-kbd-tty -qt-kbd-linuxinput -qt-mouse-pc -qt-mouse-linuxinput -openssl
make -j 8
sudo make install
fatal error: .pch/release-shared-emb-arm/QtGui: No such file or directory
touch src/gui/.pch/release-shared-emb-arm/QtGui
export QWS_KEYBOARD=linuxinput
/opt/raspi/demos/browser/browser -qws
I recently came across a problem retrieving multiple columns in Postgres, turns out the function needs to be treated as a table.test=# CREATE FUNCTION numbers(OUT INT, OUT INT, OUT INT) RETURNS SETOF RECORD AS $$ SELECT 1, 2, 3; $$ LANGUAGE 'sql';CREATE FUNCTIONtest=# SELECT numbers(); numbers --------- (1,2,3)(1 row)test=# SELECT * FROM numbers(); column1 | column2 | column3 ---------+---------+--------- 1 | 2 | 3(1 row)
I heard about libcloud on the podcast FLOSS 181, it makes it easy to access cloud things from Python. This example code lists all the file objects in all containers, to use this you will need to modify the API_ constants to your account.import libcloud.storage.providers, libcloud.storage.typesAPI_USERNAME = "xxxxxxxx"API_PASSWORD = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"API_PROVIDER = libcloud.storage.types.Provider.CLOUDFILES_UKstorage = libcloud.storage.providers.get_driver(API_PROVIDER)( API_USERNAME, API_PASSWORD)for container in storage.list_containers(): print "Container: %s" % container.name for fileobj in container.list_objects(): print "> Object: \"%s\", Size: %d bytes" % (
fileobj.name, fileobj.size)
To use slots and signals in another thread, you need an event loop running.
Inside the run method of your thread, you need to call exec.
You can do setup and tear-down before and after if needed, for example:
void MyThread::run()
{
// Setup code here
exec();
// Tear-down code here
}
To leave the event loop and finish your thread, you can call the exit slot on the thread.
The default implementation of QThread::run() will just call exec, but if you re-implement run then you need to call exec yourself.
For more information, have a look at the Subclassing QThread section in the manual.
Take a look at Graphviz, this is a suite of graph layout tools and libraries and it used by many other programs for drawing graphs such as Doxygen and KCacheGrind.
You can use it either as a library, to link against; or write out a file, call the executable to process it and read the file back in. This second (file write/process/read) method is the most commonly used.
To do this you:
dot (one of the graphviz tools) with the output format as dot, this will append the layout information to the fileThere are several libraries for doing this including for Python, see pydot.
I would embed a QWebView into the UI, then once the user is logged in via this browser you can access the QNetworkAccessManager that the page has configured to send the requests.
QNetworkAccessManager* getNetMan(const QWebView* view)
{ return view->page()->networkAccessManager(); }
This should have the cookie jar configured correctly, you may need to set the HTTP Referrer header as well for this sort of system to work to spoof the request fully.
If this doesn't work, use Wireshark to compare the requests from the browser and your application, and tweak your program until you have the requests matching.
If you just need a big dictionary you may want to look at using a database that provides a Key-Value store, rather than a relational database like SQLite.
Popular Key-Value stores include:
This error message occurs when the CMake global property TARGET_SUPPORTS_SHARED_LIBS is set false and you use a shared library. See Source/cmAddLibraryCommand.cxx line 100 in the CMake source.
This shouldn't normally occur unless you are cross compiling for a very basic system (embedded OS).
I suspect that either this is a bug in the latest version of CMake or you have not configured CMake correctly.
There are a few ways to do this, as your sample is working with QWebView rather than QTextBrowser, I'll assume your working with the QWebView.
For page to application QWebView::linkClicked(const QUrl& url) signal is fired when a link is clicked, and QWebView::load(const QUrl& url) will change the page.
If you are creating a JavaScript application, have a look at the QtWebKit Bridge documentation. This allows two way communication with JavaScript running on a page.
Assuming this is a reasonably well behaved widget, you could either use:
setCentralWidget)stretch parameter of your QVTKWidget widget to 1 and your other widgets to 0, see QBoxLayout::addWidget.The OpenSSL crypto library has blowfish support. It is recommended to use the OpenSSL EVP system rather than the calls directly.
I can think of two ways to do this, the easy way, and the hard way.
Easy way:
Put a QLabel in a QScrollArea and scroll the area around, could be controlled by a QTimer.
Hard way:
Create a custom QWidget that scrolls text in its paintEvent. The benefit of this would be more control over the rendering, and possibly lower resource usage.
You will need to re-write the file with the extra nodes. The stream interface (QXmlStreamReader / QXmlStreamWriter) is more complex to use to do this than the DOM (QDomDocument) interface, but has the benefit of lower memory requirements.
With the DOM interface you work with an in-memory representation of the XML document. With the stream interface you may need to build and maintain your own representation.
Sample code for the stream interface:
QFile inputFile("in.xml");
if (! inputFile.open(QIODevice::ReadOnly))
// error handling
QFile outputFile("out.xml");
if (! outputFile.open(QIODevice::WriteOnly))
// error handling
QXmlStreamReader inputStream(&inputFile);
QXmlStreamWriter outputStream(&outputFile);
while (! inputStream.atEnd())
{
inputStream.readNext();
// manipulation logic goes here
outputStream.writeCurrentToken(inputStream);
}
Sample code for the DOM interface:
QFile inputFile("in.xml");
if (! inputFile.open(QIODevice::ReadOnly))
// error handling
QDomDocument doc;
if (! doc.setContent(&inputFile))
// error handling
// manipulation logic goes here
QFile outputFile("out.xml");
if (! outputFile.open(QIODevice::WriteOnly))
// error handling
outputFile.write(doc.toByteArray());
From the DBus Bindings page, there is a link to dbus-c++.
Disclaimer: I haven't used these projects and can not vouch for them.
Have a look at how Boost do it, the iterators in boost/container/vector.hpp - vector_const_iterator and vector_iterator are reasonably easy to understand pointer based iterators.
Compiling a program that uses Boost statically is quite simple in CMake. Using the FindBoost module handles it for you.
An example CMakeLists.txt file for a program that uses program_options statically:
cmake_minimum_required(VERSION 2.8)
project(myproj)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost 1.40 REQUIRED COMPONENTS program_options)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(myexe source_file.cpp)
target_link_libraries(myexe ${Boost_LIBRARIES})
The simplest solution may be to add HINTS to each find_* request.
For example:
find_library(CURL_LIBRARY
NAMES curl curllib libcurl_imp curllib_static
HINTS "${CMAKE_PREFIX_PATH}/curl/lib"
)
For Boost I would strongly recommend using the FindBoost standard module and setting the BOOST_DIR variable to point to your Boost libraries.
The only error handling is via the exception read_xml throws.
You may want to consider validating the document against a schema you write before passing the XML to boost::property_tree.
There is no Boost XML library currently, so you may want to look at validation using Xerces-C++ Schema Support or another equivalent library.
Have a look at the following standard CMake modules:
Examples of using FeatureSummary (from manual):
option(WITH_FOO "Help for foo" ON)
add_feature_info(Foo WITH_FOO "The Foo feature provides very cool stuff.")
find_package(LibXml2)
set_package_properties(LibXml2 PROPERTIES DESCRIPTION "A XML processing library." URL "http://xmlsoft.org/")
set_package_properties(LibXml2 PROPERTIES TYPE RECOMMENDED PURPOSE "Enables HTML-import in MyWordProcessor")
set_package_properties(LibXml2 PROPERTIES TYPE OPTIONAL PURPOSE "Enables odt-export in MyWordProcessor")
feature_summary(WHAT ALL)
The standard library streams have two modes:
State checking - the programmer must call good(), eof(), fail() or bad() to detect problems.
Exception throwing - the programmer calls exceptions(...) to set an exception mask, see the link for an example.
The Qt library typically does not use exceptions, the QIODevice class (and hence QFile) will return a bool for the success or failure of a call. The error message can be obtained from QIODevice::errorString().
You could look at GNU libmicrohttpd (LGPL licence), this is a cross platform HTTP server library for embedding into applications. It is reasonably easy to get started with.
For the port-forwarding part, you could have a look at MiniUPnP (BSD licence), I've not used this library and can't vouch for it working.
Any UPnP library should do the trick, the basic steps would be:
If steps 2 or 3 fail you would need to provide instructions to the user on how to do it (send them to portforward.com).
I would recommend using mod_wsgi (rather than mod_python), as WSGI is the standard way to host Python web applications.
You need to have a function called application in the global scope, in your case:
# ....
return results
soap_application = soaplib.core.Application([HelloWorldService], 'tns')
application = wsgi.Application(soap_application)
if __name__ == "__main__":
# ....
You then enable mod_wsgi in Apache and add directives in (WSGIScriptAlias is the main one). The help pages are reasonably accessable if you've configured Apache before.
You should look at QTestLib:
The QTestLib framework, provided by Nokia, is a tool for unit testing Qt based applications and libraries. QTestLib provides all the functionality commonly found in unit testing frameworks as well as extensions for testing graphical user interfaces.
It adds the QTest namespace which contains several functions for testing QtGui applications including:
keyClick - Send a keyboard keymouseClick - Send a mouse clickqWaitForWindowShown - Wait for a window to appearOne way to do this would be to first create a new class inheriting from QNetworkManager that overrides QNetworkAccessManager::createRequest. In your createRequest function you would first call the base/super class to get the request, then connect to the QNetworkReply::error signal or QNetworkReply::finished and check the QNetworkReply::error function.
You then set this custom QNetworkAccessManager on the QWebPage with QWebPage::setNetworkAccessManager.
To intercept JavaScript messages, you create a new class inheriting from QWebPage that overrides QWebPage::javaScriptConsoleMessage. Any errors or calls to console.log will be passed to this function:
This function is called whenever a JavaScript program tries to print a message to the web browser's console. For example in case of evaluation errors the source URL may be provided in sourceID as well as the lineNumber.
Note: This answer assumes that PySide provides the full Qt API, I haven't actually checked this is possible in Python, but it's the way I've previously done similar things in C++.
To layout the graph, you may want to look at GraphViz - a graph visualisation tool.
You could just use the GraphViz algorithms for layout (using plain output) and then draw using the Qt libraries (QGraphicsScene / QGraphicsView like @cbamber85 recommended), or you could render a PNG from GraphViz and then display it.
You may want to look at KCacheGrind, as this is a Qt application that uses GraphViz for laying out call graphs.
I think what you are looking for is QNetworkConfigurationManager which was added in Qt 4.7.
QNetworkConfigurationManager provides access to the network configurations known to the system and enables applications to detect the system capabilities (with regards to network sessions) at runtime.
It has signals for configurations being added and removed.
It can also trigger a scan with the updateConfigurations() slot (a signal will be emitted when complete):
Initiates an update of all configurations. This may be used to initiate WLAN scans or other time consuming updates which may be required to obtain the correct state for configurations.
You can set the connection a QNetworkAccessManager uses by calling QNetworkAccessManager::setConfiguration.
As you are using the QByteArray QIODevice::read(qint64 maxSize) function, you may not be detecting errors correctly:
This function has no way of reporting errors; returning an empty QByteArray() can mean either that no data was currently available for reading, or that an error occurred.
Some things to try:
Use the qint64 QIODevice::read(char* data, qint64 maxSize) which reports errors:
If an error occurs ... this function returns -1.
Call QIODevice::errorString and QAbstractSocket::error to find out what is going wrong.
QAbstractSocket::error error signal.If this is a new protocol you are creating, try using QDataStream for serialization, this automatically handles length prefixs and is platform independent. Your char_to_int32 will break if you mix platforms with different endienness, and may break between different OSs or compilers as int is not guaranteed to be 32 bits (it is defined as at least 16 bits).
QDataStream, at least use the htons, ntohs ... functions.Edit
Here is some example code showing hton/ntoh usage. Note that uint32_t and not int is used as it's guaranteed to be 32 bits. I've also used memcpy rather than pointer casts in the encode/decode to prevent aliasing and alignment problems (I've just done a cast in the test function for brevity).
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
void encode(uint32_t in, char* out)
{
/* Host to Network long (32 bits) */
const uint32_t t = htonl(in);
memcpy(out, &t, sizeof(t));
}
uint32_t decode(char* in)
{
uint32_t t;
memcpy(&t, in, sizeof(t));
/* Network to Host long (32 bits) */
return ntohl(t);
}
void test(uint32_t v)
{
char buffer[4];
printf("Host Input: %08x\n", v);
encode(v, buffer);
printf("Network: %08x\n", *((uint32_t*)buffer));
printf("Host Output: %08x\n\n", decode(buffer));
}
int main(int argc, char** argv)
{
test(0);
test(1);
test(0x55);
test(0x55000000);
return 0;
}
The simpler way as mentioned by @Stephen Chu is using QGraphicsScene.
Here is an example that prints with qdebug when you click on a rectangle.
clickrect.hpp
#ifndef _HANDLER_HPP_
#define _HANDLER_HPP_
#include <QtGui>
class ClickRect : public QGraphicsRectItem
{
public:
ClickRect(
const QRect& rect,
const QColor& color,
const QString& name,
QGraphicsItem* parent = 0);
protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent* event);
private:
QString mName;
};
#endif
clickrect.cpp
#include "clickrect.hpp"
ClickRect::ClickRect(
const QRect& rect,
const QColor& color,
const QString& name,
QGraphicsItem* par
) :
QGraphicsRectItem(rect, par),
mName(name)
{
setBrush(QBrush(color));
}
void ClickRect::mousePressEvent(QGraphicsSceneMouseEvent* ev)
{
qDebug() << mName;
}
test.cpp
#include <QtGui>
#include "clickrect.hpp"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QGraphicsScene scene;
QGraphicsView view(&scene);
view.show();
ClickRect rect_a(QRect(0, 0, 30, 30), QColor("#FDD"), "A");
ClickRect rect_b(QRect(40, 0, 30, 30), QColor("#DFD"), "B");
scene.addItem(&rect_a);
scene.addItem(&rect_b);
return app.exec();
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
find_package(Qt4 4.8 REQUIRED QtCore QtGui)
include(${QT_USE_FILE})
add_executable(test
test.cpp
clickrect.hpp
clickrect.cpp
${MOC_FILES})
target_link_libraries(test ${QT_LIBRARIES})
I don't think there is a simple way to do this using QML. You can do this with the standard QWebView, but there isn't a way to access this functionality from within QML. You would need to re-wrap QWebView and expose more functions.
An example using the standard C++ interfaces:
test.cpp
#include <QtGui>
#include <QtWebKit>
#include "handler.hpp"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QWebView view;
view.load(QUrl::fromUserInput("http://qt-project.org/"));
view.page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
LinkHandler handler;
QObject::connect(
&view, SIGNAL(linkClicked(const QUrl&)),
&handler, SLOT(open(const QUrl&)));
view.show();
return app.exec();
}
handler.hpp
#ifndef _HANDLER_HPP_
#define _HANDLER_HPP_
#include <QtGui>
class LinkHandler : public QObject
{
Q_OBJECT
public:
LinkHandler();
public slots:
void open(const QUrl& url);
};
#endif
handler.cpp
#include "handler.hpp"
LinkHandler::LinkHandler() : QObject() {}
void LinkHandler::open(const QUrl& url)
{
QDesktopServices::openUrl(url);
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
find_package(Qt4 4.8 REQUIRED QtCore QtGui QtWebkit)
include(${QT_USE_FILE})
qt4_wrap_cpp(MOC_FILES handler.hpp)
add_executable(test
test.cpp
handler.hpp
handler.cpp
${MOC_FILES})
target_link_libraries(test ${QT_LIBRARIES})
There are a few things wrong with this code:
You are using shell redirection (>) in add_custom_command but you have specified the VERBATIM flag which doesn't process via the shell.
You are not enclosing your paths in quotes, which will cause problems if they contain spaces, set(DIR ... should be: set(DIR "${CMAKE_CURRENT_SOURCE_DIR}/")
You are creating files within the source tree; CMake is usually used with out of source builds so temporary files should be created in the build tree
You could use file(WRITE to create the file, which will be faster than calling out to the shell
cmake_minimum_required is missing
Fixed CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
set(DIR "${CMAKE_CURRENT_BINARY_DIR}")
file(MAKE_DIRECTORY "${DIR}")
file(WRITE "${DIR}/test.cc" "int main(void) {}")
add_executable(test "${DIR}/test.cc")
Don't use nested toolbars, it isn't a good idea. Instead use a QMainWindow, and add multiple toolbars to the window. This will allow the users to move them around, unlike adding a toolbar directly to a widget.
Example web-browser with hard-coded bookmarks: (note, don't do bookmarks like this in production code)
win.h
#ifndef _WIN_H_
#define _WIN_H_
#include <QtGui>
#include <QtWebKit>
class TestWindow : public QMainWindow
{
Q_OBJECT
public:
TestWindow();
private slots:
void loadUrl(const QString& url);
private:
QWebView* mView;
QSignalMapper* mUrlMap;
Q_DISABLE_COPY(TestWindow)
};
#endif
win.cpp
#include "win.h"
TestWindow::TestWindow() :
QMainWindow(),
mView(new QWebView()),
mUrlMap(new QSignalMapper(this))
{
setCentralWidget(mView); // Takes ownership
mView->load(QUrl::fromUserInput("http://qt-project.org/doc/"));
connect(mUrlMap, SIGNAL(mapped(const QString&)), this, SLOT(loadUrl(const QString&)));
QToolBar* tools = addToolBar("Tools");
tools->addAction(mView->pageAction(QWebPage::Back));
tools->addAction(mView->pageAction(QWebPage::Forward));
tools->addAction(mView->pageAction(QWebPage::Stop));
tools->addAction(mView->pageAction(QWebPage::Reload));
QToolBar* bookmarks = addToolBar("Bookmarks");
QAction* bkmkQtDoc = bookmarks->addAction(tr("Qt Documentation"));
QAction* bkmkBbc = bookmarks->addAction(tr("BBC News"));
connect(bkmkQtDoc, SIGNAL(triggered(bool)), mUrlMap, SLOT(map()));
connect(bkmkBbc, SIGNAL(triggered(bool)), mUrlMap, SLOT(map()));
mUrlMap->setMapping(bkmkQtDoc, "http://qt-project.org/doc/");
mUrlMap->setMapping(bkmkBbc, "http://www.bbc.co.uk/");
}
void TestWindow::loadUrl(const QString& url)
{
mView->load(QUrl::fromUserInput(url));
}
test.cpp
#include <QtGui>
#include "win.h"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
TestWindow win;
win.show();
return app.exec();
}
test.pro
QT += core gui webkit
SOURCES=test.cpp win.cpp
HEADERS=win.h
If you want to heap allocate your People but use a map, have a look a Boost Pointer Containers, specifically the boost::ptr_map. It's header only, so you don't need to compile any extra libraries.
#include <iostream>
#include <string>
#include <boost/ptr_container/ptr_map.hpp>
struct People
{
int age;
};
typedef boost::ptr_map<std::string,People> PeopleMap;
int main(int,char**)
{
PeopleMap data;
data["Alice"].age = 20;
data["Bob"].age = 30;
for (PeopleMap::const_iterator it = data.begin(); it != data.end(); ++it)
std::cout << "Name: " << it->first << " Age: " << it->second->age << std::endl;
return 0;
}
If you don't need interaction with the page, you could call QWebFrame::render(QPainter* painter, const QRegion& clip) and draw it onto a widget, specifying clip to be the required area.
Have you compared the requests using Wireshark?
rpath.@SamuelNLP have you tried setting the stretch factor?
@SamuelNLP You need to say why, your comment by itself provides no useful information for someone to assist you with the problem. At a guess through is your problem the same as here: vtk.org/pipermail/vtkusers/2010-November/113376.html ?
@Xeo What if someone implemented a doubly linked list using smart pointers ?
This is why I described it as the hard way! You need to take into account the size of the widget (QWidget::size() or QWidget::rect()), do the maths and position the text correctly. You could also look at using QPainter::drawText with the alignment flags to position the text. Make sure you test your widget with different fonts (faces, sizes, languages) to check that it will work on other computers.
In CMake you should use find_package(Boost ... to locate Boost and use target_link_libraries to specify libraries; this helps when porting to other compilers / OS.
@leemes Sorry, I don't use QtDesigner, I can't help with that
As I explained in my answer the QML WebView Element doesn't provide the full interface of QWebView, so you can't use the standard QML WebView to do what you want.
On StackOverflow the best way to mark a question as fixed is to add your own answer and then accept that rather than editing the original post, the question then gets marked as solved in the list of questions.
Could you run your schema through the xmlpatternsvalidator tool (part of QtXmlPatterns) to check whether Qt can parse the schema?
Update your question to include the exact API call you are making, preferably with a link to the documentation. Also try to provide a code snippet demonstrating the upload. You could also try to perform the upload using cURL to quickly check you are sending correctly before writing it in Qt/C++
Qt 5 may improve time-zone support (qt-project.org/forums/viewthread/11559/#63362) but I don't think anything is improved yet.
Software engineer with wide ranging experience from many projects.
Software Engineer working on Set Top Box Conditional Access Modules
Software engineer, designing, developing and maintaining software in C++.