I'm working on translating our Qt gui at the moment.
I have the following code:
// header file
static const QString Foo;
// cpp file
const QString FooConstants::Foo = "foo";
// another cpp file
editMenu->addAction(tr(FooConstants::Foo));
This doesn't seem to work though.
That is, there is no entry in the .ts file for the above constant.
If I do this then it works:
// another cpp file
editMenu->addAction(tr("foo"));
However, this constant is used in many places, and I don't want to have to manually update each string literal. (if it were to change in the future)
Can anyone help?
Wrap your literal in the QT_TR_NOOP macro:
// cpp file
const QString FooConstants::Foo = QT_TR_NOOP("foo");
From the guide:
If you need to have translatable text completely outside a function, there are two macros to help: QT_TR_NOOP() and QT_TRANSLATE_NOOP(). They merely mark the text for extraction by the lupdate tool. The macros expand to just the text (without the context).
As Thomas mentioned, you have to use a macro.
The reason is that Qt doesn't know which strings to translate by default, it scans the files and looks for a set of patterns. One of them is tr("text"), but if you want to use a constant, you will have to mark it explicitly with QT_TRANSLATE_NOOP or QT_TR_NOOP when it's defined.
editMenu->addAction(tr(FooConstants::Foo));
I think your problem is that tr takes a char* argument, not a QString:
QString QObject::tr ( const char * sourceText, const char * disambiguation = 0, int n = -1 )
You could change the type of FooConstants::Foo, or convert it to a char* when you create the menu action, for example:
const QByteArray byteArray = FooConstants::Foo.toLatin1();
char *data = byteArray.data();
editMenu->addAction(tr(data));
Related
Hello everyone I am trying to get to know pointers better and I stumbled into a Qt type change. I have made a QString array and gave the pointer to the array to a method. But when I try to use a QString functions it give a error and says that it is a QCharRef which does not have the member function isEmpty().
The code:
QString data_array[2][3] =
{
{"11:28:8","Room 1","Presence detected"},
{"11:38:8","Room 1","No presence"}
}
bool method(QString *_data_array)
{
QString *data_array = _data_array;
return data_array[0][1].isEmpty(); /* changed to QCharRef */
}
My question is why does this happen and how can I prevent it or change it?
The reason for which you are getting QCharRef is due to how QString is built. The [] operator returns one character from a QString (QString is built up from QChars, much like strings in C/C++ are character arrays). From the Qt documentation:
The return value is of type QCharRef, a helper class for QString. When you get an object of type QCharRef, you can use it as if it were a QChar &. If you assign to it, the assignment will apply to the character in the QString from which you got the reference.
So what that means for you is that when you use the lovely square bracket operators, you are no longer using a QString, you are using a QChar reference.
As for how to change it, QChar's isNull() seems like it would fit your uses. so instead try return data_array[0][1].isNull(); and that should work.
I would also look into QStringList if you're doing things with lists of strings
I want to replace a flow of transforming QString to char* in Qt4:
str.toLatin1().data()
to the same in Qt3:
str.latin()
using some construction as:
#define toLatin1().data() latin()
Is it really? Is there another way to do this?
I'd say the most maintainable solution would be to introduce a function for it:
inline const char* qstringToLatinChar(const QString &str)
{
#if Qt4
return str.toLatin1().data();
#else
return str.latin();
#endif
}
Such a function can quickly be substituted at existent code sites even with sed or the like. It has the added benefit of introducing a meaningful name for the operation.
In Qt 4 it is possible to automatically cast a QString to a "const char *", e.g. I could pass a QString to a function that expected a "const char *".
void myFunction(const char *parameter);
QString myString;
myFunction(myString); //works in QT4
In Qt 5 I would however get an "error C2440: 'type cast' : cannot convert from 'QString' to 'const char *'" (that is the Visual C++ 2008 compiler, other compilers would throw something similar). If I understand the documentation correctly, it is because the Qt 3 compatibility layer is not included anymore in QT5.
Of course, I could change the function call from
myFunction(myString);
to
myFunction(myString.toLatin1().data());
However, I have a huge code base that compiles fine with Qt 4 and I would really like to have my old code compile with Qt 5 without modifying it. Is there any way to achieve this?
You could create a macro or inline function for your purpose to minimize the changes, but since that would also require a grep alike operation, there is not much difference.
#define QString2charp(myString) myString.toLatin1().data()
or
inline char* QString2charp (const QString &myString)
{
return myString.toLatin1().data();
}
and then:
myFunction(QString2charp(myString));
BUT
of course, in an ideal world, it would be nice if your "myFunction" could get an overload expecting a QString argument.
void myFunction(const char *parameter);
void myFunction(QString parameter);
and then the overload would be implemented like this:
void myFunction(const QString ¶meter)
{
myFunction(myString.toLatin1().data());
}
of course, this would require the constructor being explicit so that no implicit conversion can happen, otherwise the compiler will complain about ambiguity in presence of both when trying to pass const char*, but if you always use QString, it should just work with Qt 5.
This is somewhat equal to rewriting the original function to a different signature expecting QString though because unfortunately the corresponding constructor is not explicit. I imagine that was not changed in Qt 5 for compatibility as it would have broken too much code.
As you can see, you do not need to change anything in your code this way, other than adding a one-liner overload. It is neat, isn't it?
You could either
Change the signature of your function to MyFunction( const QString & parameter ) (of course that works only if you don't need the one that takes char * any more)
Overload MyFunction:
void myFunction(const char *parameter); //this is your normal function
void myFunction( const QString & parameter )
{
char * c_str = nullptr;
<convert parameter to char * in any way that suits you>
myFunction( c_str );
}
If the above is impossible for some reason, the best approach is probably to write a similar wrapper:
void MyFunctionWrapper( const QString & parameter )
{
<same as above>
}
It is no longer possible to cast QString to const char* in >= Qt 5, because QString is UTF-16 and no longer has an entry for caching the result of converting to ASCII.
The way to achieve your aim is
a) Add overloads to the functions expecting const char* which can handle QStrings,
b) Add the explicit conversion code to the call-site, or
c) Go to some char-based string, like std::string.
None of those fulfill your aim of nearly no changes though.
I found this on QT forum
const QByteArray byteArray = mytext = textBox.text().toUtf8();
const char *mytext = byteArray.constData();
This resolved my issue
I have a DLL that I need to handle in C++. I'm using WxWidgets (standard compilation, but I also tried Unicode on/off) and NetBeans. I also tried dealing with this without WxWidgets (windows.h) and had same problems.
Here is how I access the DLL functions using WxWidgets:
// -------------------- POINTERS TO FUNCTIONS
typedef bool(*TYPE_DLL_SetLicense)(char*, char*);
typedef bool(*TYPE_DLL_PingConnection)(char*);
typedef char*(*TYPE_DLL_ERR_DESCRIPTION)(void);
class DLL_Library
{
public:
// pointers to functions inside dll
TYPE_DLL_SetLicense DLL_SetLicense; //initialize - will wor fine as it returns only true/false (buffer only provide data)
TYPE_DLL_PingConnection DLL_PingConnection; //ping to serwer. Will return trahs, becouse it uses buffer to provide data ang get answear back
TYPE_DLL_ERR_DESCRIPTION DLL_ERR_DESCRIPTION; //error description. No buffer, no trouble. Returns correct string.
wxDynamicLibrary dynLib2;
int initialize(void)
{
//patch to dll
wxString path = wxStandardPaths::Get().GetExecutablePath().BeforeLast('\\') + _("\\DLL_dll\\DLLMOK.dll");
if(!wxFile::Exists(path)) return -1;
//load dll
if(!dynLib2.Load(path)) return -2;
//Assign functions in dll to variable
DLL_SetLicense=(TYPE_DLL_SetLicense) dynLib2.GetSymbol(wxT("DLL_SetLicense"));
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
DLL_ERR_DESCRIPTION=(TYPE_DLL_ERR_DESCRIPTION) dynLib2.GetSymbol(wxT("DLL_ERROR_DESCRIPTION"));
return 0;
}
};
And here is the function I run. It should return and XML content, that I try to save to the file.
//DLL_PingConnection
//result ping to be save in file
wxFile file_ping_xml;
plik_ping_xml.Open(wxT("C:\\dll\\ping.xml"),wxFile::write);
char buffor_ping_xml[2000];
//I run the function here
bool is_ping = DLL_PingConnection(buffor_ping_xml);
if(is_ping)
{
tex_box->AppendText(wxT("DLL_PingConnection True\n"));
//we save result to file
bool is_write_ping_ok = file_ping_xml.Write(buffor_ping_xml,2000);
if (is_write_ping_ok){tex_box->AppendText(wxT("Save to file is ok ok\n"));}
else {tex_box->AppendText(wxT("Save to file failed :( \n"));}
}
else
{
tex_box->AppendText(wxT("DLL_PingConnection False\n"));
}
std::cout << "Error description: " << DLL_ERR_DESCRIPTION() << "\n"; //will work fine both in saving to file, and in streaming to screen.
The problem is that inside the file instead of good content I get rubbish like this:
NOTE that this only happens in functions that use buffers like:
char buffer[2000] //buffer will contain for example file xml
function do_sth_with_xml(buffer) //buffer containing xml will (should) be overwriten with xml results of the function - in our case DLL_PingCONNECTION should save in buffer xml with connection data
Documentation say that the DLL operates on Windows-1250. File ping.xml I have set to windows ANSI, but I don't think problem lies here.
EDIT: I have written problem without WxWidgets (I load DLL using windows.h) - same problems. Here is the code: Getting trash data in char* while using it as buffer in function . Please help :(
This
DLL_PingConnection=(TYPE_DLL_PingConnection)
shouldn't it be
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(wxT("DLL_PingConnection"));
?
seems otherwise you will not get a valid pointer to the function in the DLL.
as a general rule you should check return values, especially from a DLL
you load dynamically since it happens that you sometimes get another version
of the DLL which may have a function with same name but other signature or
where is missing entirely.
You named a function
DLL_PingConnection=(TYPE_DLL_PingConnection) dynLib2.GetSymbol(....
and call it with
OSOZ.OSOZ_PingConnection(buffor_ping_xml);
you typedef a function
typedef bool(*TYPE_DLL_PingConnection)(char*);
you create a variable
char buffor_ping_xml[2000];
in your typedef it is char* and your buffor_ping_xml is char
how can that work ?
try
char *buffor_ping_xml = new char[2000];
/* or */
wchar_t *buffor_ping_xml = new wchar_t[2000];
/* or */
wxChar *buffor_ping_xml = new wxchar[2000];
bool is_ping = DLL_PingConnection(buffor_ping_xml);
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
write mystring to file.
To Do:
look in your wxwidgets\libs folder for your libs
are there libwxmsw29ud_* with a 'u' in the name (after version number here 29)?
If not You can not use unicode
If yes next steps
for all different test char *, wchar_t *, wxChar * give the files different name.
for example file_ping_xml.Open(wxT("C:\dll\ping_w_t_FromUTF8.xml"), ...
for wchar_t * in combination with
wxString mystring = wxString::FromUTF8(buffor_ping_xml);
also in combination with
wxString mystring(buffor_ping_xml);
Then check out the look like, of the files in a browser .
To test you can go to your wxWidgets sample folder . Compile in the folder C:\wxWidgets\samples\docview\docview.cpp . Open with docview.exe a unicode file . How does it look.
Unicode download file
Unicode-related compilation settings
You should define wxUSE_UNICODE to 1 to compile your program in Unicode mode. This currently works for wxMSW, wxGTK, wxMac and wxX11. If you compile your program in ANSI mode you can still define wxUSE_WCHAR_T to get some limited support for wchar_t type.
Here is answear: Getting trash data in char* while using it as buffer in function.
Thanks everyone - expecially for patience.
I'm writing a Cocos2D-X game where the player, enemies and other characters store their attributes in a CCMutableDictionary, which is somewhat of a decorator class for std::map<std::string, CCObject*>. A value in the dictionary can be accessed via the CCMutableDictionary::objectForKey(const std::string& key) method.
Now, in a header file included by many of my .cpp files, I've got a few const char * const strings for accessing values in the dictionaries, like this:
// in Constants.h
const char* const kAttributeX = "x";
const char* const kAttributeY = "y";
// in a .cpp file
CCObject* x = someDictionary->objectForKey(kAttributeX);
So, correct me if I'm wrong, but std::string's copy constructor is being called and a temporary std::string is on the stack every time I call one of the above objectForKey methods using a const char* const, right?
If so, I feel that it would be more efficient at runtime if those constant attribute keys were already std::string objects. But how do I do that the right way?
Defining them in the Constants.h file like the following compiles fine, but I have a feeling that something just isn't right:
// in Constants.h
const std::string kAttributeX = "x";
const std::string kAttributeY = "y";
My apologies if this question has already been asked. I couldn't seem to find the exact answer I was looking for here on StackOverflow.
The code you wrote is perfectly fine, at least as you only #include the Constants.h file in only one source file. If you use the header file in multiple source files, you will have the same variables defined multiple times. The correct use of constants in header files are to split them into a header (Constants.h) which contains the declarations of the variables, and a source file (Constants.cpp) which contains the definitions of the variables:
The header file:
#ifndef CONSTANTS_H
#define CONSTANTS_H
extern const std::string kAttributeX;
extern const std::string kAttributeY;
#endif
The source file:
const std::string kAttributeX = "x";
const std::string kAttributeY = "y";
Your second option causes each of the variables to be created in every translation unit (cpp file that includes the header) which will slightly increase code size as well as adding a bit of runtime cost (constructing all those string during launch and destructing them during process termination).
The solution suggested by Joachim works but I find declaring and defining variables separately to be a bit of a drag. I personally hate repeating myself, also I don't like saying the same thing over and over again...
I don't know of a good solution for this in C++ proper but the compilers I've worked with all support something like __declspec( selectany ) so that you can define the variable in the header file and only get one object instantiated (rather than one for each translation unit).
__declspec( selectany ) extern const std::string kAttributeX = "x";
(For why both extern and const see this answer).
You still have the drawback of paying the initialization price of all the global variables during process launch. This is acceptable 101% of the time (give or take 2%) but you can avoid this by using lazy objects (I've written about something similar here).