For some reasons, I must work with Qt3 under SLES 11 SP3. I have written the following plugin:
// PixmapButtonPlugin.hpp
#include <qwidgetplugin.h>
class PixmapButtonPlugin : public QWidgetPlugin
{
public:
QStringList keys () const;
QWidget* create (const QString& key, QWidget* parent = 0, const char* name = 0);
QString group (const QString& key) const;
QIconSet iconSet (const QString& key) const;
QString includeFile (const QString& key) const;
QString toolTip (const QString& key) const;
QString whatsThis (const QString& key) const;
bool isContainer (const QString& key) const;
};
Q_EXPORT_PLUGIN(PixmapButtonPlugin)
// PixmapButtonPlugin.cpp
#include "PixmapButtonPlugin.hpp"
#include "PixmapButton.qh"
QStringList PixmapButtonPlugin::keys () const
{
return QStringList() << "PixmapButton";
}
QWidget* PixmapButtonPlugin::create (const QString&, QWidget* parent, const char*)
{
return new PixmapButton(parent);
}
QString PixmapButtonPlugin::group (const QString&) const
{
return "Buttons";
}
QIconSet PixmapButtonPlugin::iconSet (const QString& key) const
{
return QWidgetPlugin::iconSet(key);
}
QString PixmapButtonPlugin::includeFile (const QString&) const
{
return "PixmapButton.qh";
}
QString PixmapButtonPlugin::toolTip (const QString&) const
{
return "Pixmap button";
}
QString PixmapButtonPlugin::whatsThis (const QString&) const
{
return "Button that takes the shape of its pixmap";
}
bool PixmapButtonPlugin::isContainer (const QString&) const
{
return false;
}
I have finally copied the compiled shared library libplugins.so in the folder
/usr/lib/qt3/plugins/designer
The designer doesn't display the plugins anywhere and doesn't tell me that it couldn't create the corresponding widget either. I get absolutely no error.
What should I do?
I got some help at work from a senior developer and actually found a way out of this problem. The main issue here is to make sure that the plugin is ok. How can I check that everything is fine with my plugin? That's pretty simple.
First, compile the following simple application:
// PluginLoader.cpp
#include <iostream>
#include <qlibrary.h>
#include <private/qcom_p.h>
int main(int argc, char *argv[])
{
QLibrary lib("/path-to-my-plugin/myPlugin.so");
std::cout << "Load: " << lib.load() << std::endl;
std::cout << "Resolve: " << (lib.resolve("ucm_instantiate") != 0) << std::endl;
return 0;
}
Second, activate some debugging tools for libraries: type the following commands in a console
export LD_WARN=1
export LD_VERBOSE=1
export LD_DEBUG=all
Note that there are many other options than "all" for the LD_DEBUG variable. Just type
export LD_DEBUG=help
to get more details (you will get the details as soon as you launch the above application).
Then, launch the PluginLoader application
./PluginLoader 2> loader.log
The file loader.log will then contain all the details regarding the libraries that are being loaded, in particular messages starting with
symbol lookup error
which indicate that something is missing in the plugin.
When the PluginLoader is happy, i.e. when it says
Load: 1
Resolve: 1
you are normally ready to use the plugin in the Qt Designer. To use it, copy it in the folder
/usr/lib/qt3/plugins/designer
or
$QTDIR/plugins/designer
which is the default folder for the designer's plugins. You may also be successful by setting the
LD_LIBRARY_PATH
QT_PLUGIN_PATH
appropriately.
Usually, you can also simply
ldd /path-to-your-plugin/myPlugin.so
This will show you which libraries this plugin was linked against. This can provide you with information about libraries that you may have forgotten ...
And a last comment. I am developing on SLES 11 SP3 64 bits. However, I am compiling 32-bits applications. In particular, the plugin is 32 bits. Before trying to let the plugin appear in the designer, make sure that the designer is the 32-bit version. Otherwise, the plugin won't appear in the list.
Note also that this process can also be applied to the production of Qt4 and Qt5 plugins (maybe modulo a few adaptions)!
Related
Hello I am new to Vulkan and c++.
I am following a tutorial on Vulkan for Visual-Studio and stuck at creating a Vulkan Instance. Through a lot of googling I found out that the error -9 (VK_ERROR_INCOMPATIBLE_DRIVER) is based on the Vulkan Version 1.3, me using MacOS and how it implements the MoltenVk or must be included or something else like that.
There it got too complicated for me.
I have tried to search through the documentations and now I don't really even understand what MoltenVk is or how I even tried to include Vulkan with cmake in my project.
I may found a solution on [here] and on stackoverflow (Why does vkCreateInstance return "VK_ERROR_INCOMPATIBLE_DRIVER" on MacOS despite vulkan supported GPU and up to date driver?) but I am not able to implement/understand it. Maybe somebody can explain it or tell me how to implement it?.
The Site said I should put something like that in
std::vector<const char*>
extNames.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
extNames.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
VkInstanceCreateInfo inst_info = {};
ins_info.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
inst_info.enabledExtensionCount = static_cast<uint32_t>(extNames.size());
inst_info.ppEnabledExtensionNames = extNames.data();
I have tried it that way and with some deviations in the vk_device.cpp file without any success.
My Project basically looks like this:
Project
--.vscode
--bin
->Project.exe
--build
--CMakeFiles
--libs
--SDL
--src
--Vk_base
->vk_base.h
->vk_device.cpp
->main.cpp
->CMakeList.txt
vk_base.h:
#include <vulkan/vulkan.h>
struct VulkanContext {
VkInstance instance;
};
VulkanContext* initVulkan();
vk_device.cpp:
#include "vk_base.h"
#include <iostream>
bool initVulkanInstance(VulkanContext* context) {
VkApplicationInfo appInfo = {};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Vulkan App";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "No Engine";
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.apiVersion = VK_VERSION_1_0;
VkInstanceCreateInfo createInfo = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO};
createInfo.pApplicationInfo = &appInfo;
createInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; // MAC OS SPECIFIC
//createInfo.enabledExtensionCount = static_cast<uint32_t>(extNames.size()); // MAC OS SPECIFIC
//createInfo.ppEnabledExtensionNames = extNames.data(); // MAC OS SPECIFIC
VkResult creation_result = vkCreateInstance(&createInfo, 0, &context->instance);
std::cout << creation_result << std::endl;
return true;
}
VulkanContext* initVulkan() {
VulkanContext* context = new VulkanContext();
if (initVulkanInstance(context) != VK_SUCCESS) {
throw std::runtime_error("failed to create instance!");
}
return context;
}
main.cpp
#include <iostream>
#include <SDL.h>
#include "vk_base/vk_base.h"
bool handleMessage() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
return false;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) {
return false;
}
break;
}
}
}
int main() {
SDL_Init(SDL_INIT_VIDEO);
SDL_Window *_window;
_window = SDL_CreateWindow("Game Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 700, 500, SDL_WINDOW_RESIZABLE);
SDL_Event e;
bool quit = false;
while (!quit) {
while(SDL_PollEvent(&e) != 0){
if(e.type == SDL_QUIT){
quit = true;
}
}
}
VulkanContext* context = initVulkan();
SDL_DestroyWindow(_window);
SDL_Quit();
return 0;
}
and my Cmakefile to create the Project in the build folder with the command : cmake ../ -GXcode ( I have tried it with -GXcode and without)
CMakeLists.txt:
#project name
project(Project)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/bin")
set(SOURCE_FILES src/main.cpp src/vk_base/vk_device.cpp)
#find SDL2
add_subdirectory(libs/SDL)
#find Vulkan
find_package(Vulkan REQUIRED)
#vulkan executebl
add_executable(Project ${SOURCE_FILES})
target_include_directories(Project PUBLIC libs/SDL/include)
target_link_libraries(Project PUBLIC SDL2-static)
target_link_libraries(Project PUBLIC Vulkan::Vulkan)
target_link_libraries(Project PUBLIC ${Vulkan_LIBRARIES})
Thank you for reading and sry for my bad english:)
if there are misspellings in it, it is probably not the cause of the problem and just a typo from me on this thread :p
if you are not comfortable with C++, steer away from Vulkan. One will teach you exactly the wrong lessons about the other. Vulkan is low-level API, and shows you how you should not be programming C++ in 98 % of the time.
Apple does not support Vulkan. They have their own API Metal. MoltenVK is a library that attempts to translate Vulkan function calls to Metal calls.
This API translation does not match 1:1, so the MoltenVK wrapper is not a conformant Vulkan implementation. You need to waive that it is not conformant, and that you know of and will avoid triggering the limitations:
https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VK_KHR_portability_subset
https://github.com/KhronosGroup/MoltenVK/blob/master/Docs/MoltenVK_Runtime_UserGuide.md#known-moltenvk-limitations
You waive the Vulkan conformance by adding VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR bit to the Instance creation:
#ifdef __APPLE__
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
#endif //__APPLE__
VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR is part of a Vulkan extension, so that extension needs to be enabled before using the bit, per standard Vulkan rules:
#ifdef __APPLE__
extNames.push_back( VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME );
#endif //__APPLE__
createInfo.enabledExtensionCount = static_cast<uint32_t>(extNames.size());
createInfo.ppEnabledExtensionNames = extNames.data();
#include "pch.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
using namespace std;
class LetterDistribution
{
public: char district, trace;
public: int random_num;
public : LetterDistribution(){}
public: LetterDistribution(char dis)
{
district = dis;
trace = 'Z';
}
public: string LetterNumbers()
{
random_num = rand();
string letter_no ( district + " " + random_num);
return letter_no;
}
};
int main()
{
srand(time(0));
cout << "Enter district\n"<<endl;
char dis ;
cin >> dis;
LetterDistribution ld(dis);
cout << ld.LetterNumbers();
return 0;}
I am getting error in second last line inside main "cout << ld.LetterNumbers();". I am new to c++ , I have been working on C# earlier. I shall be thankful if someone could help me .
You have 2 issues in LetterNumbers function:
You can't add to string a number, you should convert the number to string first. you can do so by std::to_string(random_num)
You can't start concatenate string with a character, since character is like number in c++, and adding anything to number is a number. You should start from a string, even an empty one.
So the whole function can be something like:
string LetterNumbers()
{
random_num = rand();
string letter_no ( std::string("") + district + " " + std::to_string(random_num));
return letter_no;
}
Another issues: (but not errors!)
in c++ you can specify public: once, and everything after it is still public, until you change it. same thing for private and protected.
instead of <stdio.h> you should use <cstdio> which is the c++ wrapper for the c header.
I'm doing a script using CAPL and am stuck for a solution to grep the login ID from Windows. Could some please help show how to get Windows user login ID from within a CAPL program code, if this is possible?
For example, if the Windows user login ID is 'kp21ml' , I want to read this ID from a CAPL function, as shown below.
byte UserIdCheck()
{
char uid[10];
byte CanMessageTrasmission;
strncpy(uid, xxxx(), 6); // where xxxx() is the unknown OS or system function that could return the login ID ?
if (strncmp(uid, "kp21ml") != 0)
{
write("Access denied!"); // Message to CANoe's Write window
CanMessageTrasmission = 0;
}
else
{
// Access ok
CanMessageTrasmission = 1;
}
return CanMessageTrasmission;
}
I use this CAPL book as my reference guide, which is very good:
http://docplayer.net/15013371-Programming-with-capl.html
But I couldn't find anything to do with system access. I would appreciate your help.
Thanks
Juno
I'm afraid you won't be able to do that directly from a CAPL script.
I generally create a CAPL-DLL and include that in my CANoe project when I need to access some OS level functionality. Though I use it mostly for accessing an external device (e.g. USB) or to interact with another program using sockets over local host, the principle is the same.
You can find more information in CANoe's documentation with examples but the CAPL-DLL source code provided in CANoe samples is a little difficult to understand.
I've attempted to strip some of the "unnecessary" parts in the following code sample; this example will create a CAPL-DLL which "exposes" the multiplyBy10 function and basically allows you to call multiplyBy10 from you CAPL script):
#define USECDLL_FEATURE
#define _BUILDNODELAYERDLL
#pragma warning( disable : 4786 )
#include "cdll.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <map>
char moduleName[_MAX_FNAME];
HINSTANCE moduleHandle;
unsigned int
CAPLEXPORT far CAPLPASCAL multiplyBy10 (unsigned char value)
{
unsigned int result = value * 10;
freopen("CONOUT$", "w", stdout);
std::cout << "multiplyBy10() - value: " << int(value) << ", result: " << result << std::endl;
return (result);
}
CAPL_DLL_INFO4 table[] =
{
{CDLL_VERSION_NAME, (CAPL_FARCALL)CDLL_VERSION, "", "", CAPL_DLL_CDECL, 0xABD, CDLL_EXPORT},
{"multiplyBy10", (CAPL_FARCALL)multiplyBy10, "CAPL_DLL", "This is a demo function", 'L', 1, "D", "", { "value"}},
{0, 0}
};
CAPLEXPORT CAPL_DLL_INFO4 far * caplDllTable4 = table;
bool
WINAPI DllMain(HINSTANCE handle, DWORD reason, void*)
{
static FILE * stream;
switch (reason)
{
case DLL_PROCESS_ATTACH:
{
moduleHandle = handle;
char path_buffer[_MAX_PATH];
DWORD result = GetModuleFileName(moduleHandle, path_buffer, _MAX_PATH);
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAX_EXT];
_splitpath_s(path_buffer, drive, dir, fname, ext);
strcpy_s(moduleName, fname);
AllocConsole();
freopen_s(&stream, "conout$", "w", stdout);
std::cout << "DLL_PROCESS_ATTACH" << std::endl;
return 1;
}
case DLL_PROCESS_DETACH:
{
std::cout << "DLL_PROCESS_DETACH" << std::endl;
FreeConsole();
fclose(stream);
return 1;
}
}
return 1;
}
#include "stdafx.h"
#include <amp.h>
#include <assert.h>
#include <iostream>
#include <vector>
#include <iostream>
#include <ppl.h>
#include<stdio.h>
#include<conio.h>
using namespace ::Concurrency;
using std::vector;
static array<double, 1> *P_GPU;
int _tmain(int argc, _TCHAR* argv[])
{
accelerator default_device(accelerator::default_accelerator);
accelerator_view acc_v = default_device.default_view;
int N = 4*4096*4096;
double *xdata = new double[N];
memset(xdata,0,N);
extent<1> e_b(N);
P_GPU = new array<double, 1>(e_b, acc_v); // dynamic allocation of array
array<double, 1> bb(e_b, xdata, acc_v);
array_view<double, 1> dest(*P_GPU);
dest.discard_data();
parallel_for_each(dest.extent, [=,&bb](index<1> idx) restrict(amp)
{
dest[idx]=bb[idx];
});
dest.synchronize();
std::cout << "before delete .." << std::endl;
std::cin.get();
delete [] xdata; // the DATA of xdata pointer is deleted ..
delete P_GPU; // the DATA GPU of P_GPU is not deleted ???
std::cout << "Hit any key to exit..." << std::endl;
std::cin.get();
return 0;
}
The binary Code was tested by Microsoft Process Explorer v16.04.
I tested a problem of dynamic allocation of array (or array_view) in C++ AMP..
I see The GPU memory was not free after deleting the P_GPU pointer !!
This program was tested on Matlab ... (mexFunction)-> I have the same problem... ..
delete P_GPU;
I need to make a dynamic allocation (GPU C++AMP) of matrix in matlab.
I find the trick but i have complication when I do a deallocation
(delete) matrix in GPU memory ....
????
deallocate GPU memory ...
I just solved this problem following: Using pointers in C++Amp
please use: std::shared_ptr<>
class FrameProcessorAmpBase
{
private:
std::shared_ptr<array<float, 2> m_frame;
public:
FrameProcessorAmpBase()
{
}
void ConfigureFrameBuffers(int width, int height)
{
m_frame = std::make_shared<array<float, 2>>(height, width));
}
I am looking for a command line parser for Qt4.
I did a small google search, and found this: http://www.froglogic.com/pg?id=PublicationsFreeware&category=getopt however it lacks support for "--enable-foo" and "--disable-foo" switches. Besides that, it looks like a real winner.
EDIT:
It seems Frologic removed this. So the best options I see are using Boost (which is not API nor ABI stable) or forking the support for kdelibs. Yay...
QCoreApplication's constructors require (int &argc, char **argv) (and QApplication inherits from QCoreApplication). As the documentation states, it is highly recommended that
Since QApplication also deals with common command line arguments, it is usually a good idea to create it before any interpretation or modification of argv is done in the application itself.
And if you're letting Qt get the first pass at handling arguments anyways, it would also be a good idea to use QStringList QCoreApplication::arguments() instead of walking through argv; QApplication may remove some of the arguments that it has taken for its own use.
This doesn't lend itself to being very compatible with other argument-parsing libraries...
However, kdelibs does come with a nice argument parser, KCmdLineArgs. It is LGPL and can be used without KApplication if you really want (call KCmdLineArgs::init).
KCmdLineOptions options;
options.add("enable-foo", ki18n("enables foo"));
options.add("nodisable-foo", ki18n("disables foo"));
// double negatives are confusing, but this makes disable-foo enabled by default
KCmdLineArgs::addCmdLineOptions(options);
KApplication app;
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
if (args->isSet("enable-foo") && !args->isSet("disable-foo"))
cout << "foo enabled" << endl;
else
cout << "foo disabled" << endl;
Untested (who ever tests what they post on S.O.?).
Since Qt 5.2 you can finally find a solution in QtCore itself: I contributed QCommandLineParser there.
This is more or less the same answer as ephemient, but with a simple regexp to help parse the args. (This way could be useful if you only need a handful of args)
Run with this:
./QArgTest --pid=45 --enable-foo
And the code:
int main(int argc, char *argv[]) {
QApplication app(argc, argv, false);
qDebug() << "QApp arg test app";
QStringList args = app.arguments();
int pid = 0;
QRegExp rxArgPid("--pid=([0-9]{1,})");
QRegExp rxArgFooEna("--enable-foo");
QRegExp rxArgFooDis("--disable-foo");
for (int i = 1; i < args.size(); ++i) {
if (rxArgPid.indexIn(args.at(i)) != -1 ) {
pid = rxArgPid.cap(1).toInt();
qDebug() << i << ":" << args.at(i) << rxArgPid.cap(1) << pid;
}
else if (rxArgFooEna.indexIn(args.at(i)) != -1 ) {
qDebug() << i << ":" << args.at(i) << "Enable Foo";
}
else if (rxArgFooDis.indexIn(args.at(i)) != -1 ) {
qDebug() << i << ":" << args.at(i) << "Disable Foo";
}
else {
qDebug() << "Uknown arg:" << args.at(i);
}
}
return 0;
}
There is also QxtCommandOptions from http://www.libqxt.org/
That package does support --disable-foo and --enable-foo via opts.addSwitch("disable-foo", &foo_disabled); and opts.addSwitch("enable-foo", &foo_enabled);. You need handle checking both, and dealing with someone specifying both (oops).
What I don't understand is how this has anything to do with QT4...
Look at this: http://code.google.com/p/qtargparser/
A really simple method is to scan "key=value" args,
put them in a table say zz.map: QString -> QVariant,
and get their values with zz.map.value( key, default ).
An example:
#include "ztest.h"
Ztest zz;
int main( int argc, char* argv[] )
{
zz.eqargs( ++ argv ); // scan test=2 x=str ... to zz.map
QString xx = zz.map.value( "xx", "" );
if( Zint( Size, 10 )) // a #def -> zz.map.value( "Size", 10 )
...
ztest.h is < 1 page, below; same for Python ~ 10 lines.
(Everybody has his/her favorite options parser;
this one's about the simplest.
Worth repeating: however you specify options, echo them to output files --
"every scientist I know has trouble keeping track
of what parameters they used last time they ran a script".)
To make QPoints etc work one of course needs a QString -> QPoint parser.
Anyone know offhand why this doesn't work (in Qt 4.4.3) ?
QPoint pt(0,0);
QDataStream s( "QPoint(1,2)" );
s >> pt;
qDebug() << "pt:" << pt; // QPoint(1364225897,1853106225) ??
Added 25nov --
// ztest.h: scan args x=2 s=str ... to a key -> string table
// usage:
// Ztest ztest;
// int main( int argc, char* argv[] )
// {
// QApplication app( argc, argv );
// ztest.eqargs( ++ argv ); // scan leading args name=value ...
// int x = Zint( x, 10 ); // arg x= or default 10
// qreal ff = Zreal( ff, 3.14 );
// QString s = Zstr( s, "default" );
// care: int misspelled = Zint( misspellled ) -- you lose
//version: 2009-06-09 jun denis
#ifndef ztest_h
#define ztest_h
#include <QHash>
#include <QString>
#include <QVariant>
#include <QRegExp>
//------------------------------------------------------------------------------
class Ztest {
public:
QHash< QString, QVariant > map;
int test; // arg test=num, if( ztest.test )
Ztest() : test( 0 ) {}
QVariant val( const QString& key, const QVariant& default_ = 0 )
{
return map.value( key, default_ );
}
void setval( const QString& key, const QVariant& val )
{
map[key] = val;
if( key == "test" || key == "Test" )
test = val.toInt();
}
//------------------------------------------------------------------------------
// ztest.eqargs( ++ argv ) scans test=2 x=3 ... -> ztest table
void eqargs( char** argv )
{
char** argv0 = argv;
char *arg;
QRegExp re( "(\\w+)=(.*)" ); // name= anything, but not ./file=name
for( ; (arg = *argv) && re.exactMatch( arg ); argv ++ ){
setval( re.cap(1), re.cap(2) );
}
// change argv[0..] -> args after all name=values
while(( *argv0++ = *argv++) != 0 ) {}
}
};
extern Ztest ztest;
// macros: int x = Zint( x, 10 ): x= arg or default 10
#define Zstr( key, default ) ztest.val( #key, default ).toString()
#define Zint( key, default ) ztest.val( #key, default ).toInt()
#define Zreal( key, default ) ztest.val( #key, default ).toDouble()
#endif
It's 2013 and still no "1st party" arg parser. Anyways..if anyone finds themselves facing the same problem and would like to avoid the learning curves that come with cmd parser libs, here is a "quick & dirty" fix for you:-
QString QArgByKey(QString key, QChar sep = QChar('\0') ) //prototype usually in separate header
QString QArgByKey(QString key, QChar sep )
{
bool sepd=sep!=QChar('\0');
int pos=sepd?qApp->arguments().indexOf(QRegExp('^'+key+sep+"\\S*")):qApp->arguments().indexOf(QRegExp(key));
return pos==-1?QString::null:
(sepd?qApp->arguments().at(pos).split(sep).at(1):(++pos<qApp->arguments().size()?qApp->arguments().at(pos):QString::null));
}
Example:-
user#box:~$ ./myApp firstKey=Value1 --secondKey Value2 thirdKey=val3.1,val3.2,val3.3 --enable-foo
Usage:
QString param1 = QArgByKey("firstkey",'='); // Returns `Value1` from first pair
QString param2 = QArgByKey("--secondkey"); // Returns `Value2` from second pair
QString param3-1 = QArgByKey("thirdkey",'=').split(',').at(0); // Returns `val3.1`
bool fooEnabled = qApp->arguments().contains("--enable-foo"); //To check for `--enable-foo`
Params can be passed in any order
Edit: Updates to this snippet will be found here
Does it have to be Qt4 specific? If not, GNU Getopt is really nice, although licensing may be a problem if you are not doing open source software.
Also for some fancy options parsing you can try gperf.
IBM has a nice tutorial on it.
Another option I ran across while looking to do this, too:
http://code.google.com/p/qgetopts/
I haven't used it though.