QTextCodec subclass - how to register my codec - qt

I need to create my own codec, i.e. subclass of QTextCodec. And I'd like to use it via QTextCodec::codecForName("myname");
However, just subclass is not enough. QTextCodec::availableCodecs() does not contain my codec name.
QTextCodec documentation does not cover the area of proper registration of a custom codec:
Creating Your Own Codec Class
Support for new text encodings can be
added to Qt by creating QTextCodec
subclasses.
The pure virtual functions describe
the encoder to the system and the
coder is used as required in the
different text file formats supported
by QTextStream, and under X11, for the
locale-specific character input and
output.
To add support for another encoding to
Qt, make a subclass of QTextCodec and
implement the functions listed in the
table below.
name()
aliases()
mibEnum()
convertToUnicode()
convertFromUnicode()
You may find it more convenient to
make your codec class available as a
plugin; see How to Create Qt Plugins
for details.
So, I've tried to dig a little into plugins' direction. But I don't want to have a separate project with plugin. Is it possible to declare plugin within the same project?
Or is there a direct way to register my codec into QTextCodec? This is preferable.

according to qtextcodex.cpp any new codec is added to the collection of registered codecs (*static QList all) by its own constructor. So creating an instance of your codec class should do the trick; code below worked fine for me:
QMyCodec myCodec;
foreach (QByteArray codecName, QTextCodec::availableCodecs())
{
QString codecNameStr(codecName);
qDebug() << codecNameStr;
}
QTextCodec* codec = QTextCodec::codecForName("MyNewCodec");
if (codec)
{
qDebug() << "found ";
qDebug() << codec->name() << '\n';
}
QTextCodec::availableCodecs returned:
"MyNewCodec"
"System"
"roman8"
"hp-roman8"
"csHPRoman8" ...
QTextCodec::codecForName returned a pointer to my codec class
hope this helps, regards

Related

doxygen -Qt5 property commenting with accessor

I am attempting to use doxygen to comment my Qt5 classes, in particular the Q_PROPERTY macro in the same manner as the Qt5 documentation. This has the property commented, with accessors and notifier if needed. Now I can produce that using Nathan Osman's and Maxim Paperno's hints from How to doxygen comment Qt properties? however although they show the accessors and notifiers correctly, in Qt5 there is also a link back from the method documentation to the property, i.e. the documentation has a link from text() and setText() to the properties documentation, rather than having their own, which I cannot reproduce.
The doxygen config for these are:
"ALIASES += accessor=\\par Access functions:^^"
"ALIASES += notifier=\\par Notifier signal:^^"
The .h file has the following as property and public method declaration. The two % characters block a link from the property accessor documentation to the method documentation the same way as in Qt. Obviously I have left out a lot of unnecessary stuff from the code..
/*!
\property MyClass::text
\brief This property holds the classes's text.
By default, this property contains an empty string.
#accessor %text(void), %setText()
*/
Q_PROPERTY(QString text READ text WRITE setText)
QString text() const;
void setText(const QString& text);
private:
QString m_text;
The cpp code has the following definition
QString MyClass::text() const
{
return m_text;
}
void MyClass::setText(const QString& text)
{
m_text = text;
}
Is there any way to reproduce this with doxygen?
Right thanks #albert for that. I did mean accessor not accessors a slight bit of finger trouble. Doxygen version is 1.8.17.
I am using doxygen to document some of my custom classes, however in Qt 5.15.0, and 4.8 at least, the documentation as in doxygen consists of lists of properties/methods etc. followed by more detailed documentation.
If there is a property with accessors, then the method in the list section links to the property details, rather than a method detail. However I haven't found a way of making that link using doxygen. The method in the list section has no link.
There is also a problem with propertied methods with the same property name and accessor name not showing documentation for the method, if you write extra for method. I tried doing it that way earlier.

How to pretty-print QString with GoogleTest framework?

I am using the GoogleTest (GTest) framework in conjunction with a Qt5 application.
Whenever a test fails using a QString argument, the framework tries to print all the involved values. However, it cannot automatically handle foreign types (Qt5's QString in this case).
QString test = "Test";
ASSERT_EQ(test, "Value");
How can I get GoogleTest to pretty print QStrings automatically (= without having to manually convert them each time)?
The GoogleTest Guide explains how you can in general teach the framework to handle custom types.
In the end, the following code snippet is all that needs to be added for GoogleTest being able to work with QStrings:
QT_BEGIN_NAMESPACE
inline void PrintTo(const QString &qString, ::std::ostream *os)
{
*os << qUtf8Printable(qString);
}
QT_END_NAMESPACE
This code MUST NOT be in the namespace of your test fixtures, but must be in the Qt namespace (or in general in the namespace where the type that should be pretty-printed is defined in).
This code MUST also be viewable from all translation units where you call a GoogleTest assertion on that particular type, otherwise it will not get used (see comments).
As a result GoogleTest now pretty prints QStrings:
You can of course also add some quotation marks to make it clearer that it comes from a QString:
*os << "\"" << qUtf8Printable(qString) << "\"";
Source: Webinar ICS Qt Test-Driven Development Using Google Test and Google Mock by Justin Noel, Senior Consulting Engineer

cannot convert cont char* to LPCWSTR

I am stuck with an error in QT compiler however it works fine with VS2010. the error states that
I have seen other posts related to the same error but non has resolved my problem in QT. I have tried _T,L or TEXT but still not working
bq. error: C2664: 'HANDLE
LoadImageW(HINSTANCE,LPCWSTR,UINT,int,int,UINT)' : cannot convert
argument 2 from 'const char *' to 'LPCWSTR' Types pointed to are
unrelated; conversion requires reinterpret_cast, C-style cast or
function-style cast
my code is as below
Bitmap::Bitmap(std::string const& file_name) {
bitmap_ = static_cast<HBITMAP>(::LoadImage(0, file_name.c_str(), IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION));
}
please share if you have any idea to resolve this
Qt does not include a compiler. On Windows you're probably either compiling with mingw or Visual C++. Either way, the issue is that you're calling a function that expects a wide character string but you're trying to hand it an 8-bit character string.
For compatibility reasons, Win32 uses a different set of API functions if you have _UNICODE defined. In your case, you do have _UNICODE defined. You can continue using the 8-bit std::string but simply change the method from LoadImage() to LoadImageA(). Or if you don't mind changing your Bitmap class, you could switch from std::string to std::wstring to take advantage of Windows' Unicode features.
But perhaps the larger question is why use Win32 to load bitmaps and std::string if you're using Qt? Qt's QImage class and QString class provide a full-featured, cross-platform strings and image loaders. Like any comprehensive framework, Qt works best if you only use external features on an as-needed basis.
I'm not sure if this method is the best, but I've used them on my projects and it works fine, see:
char *source = "Hello world";
WCHAR target[size];
MultiByteToWideChar(CP_ACP, 0, source, -1, target, size);
LPCWSTR final = target;
MessageBox(0, final, TEXT("title"), 0); //Sample usage

qt QTranslator reuse

I noticed that the Qt documentation is not very verbose on some of the aspects of the translations. I was fooling around with it trying to figure out their behaviour using trial & error. The ultimate goal is to get the translation changed on runtime but I am very confused as to what extent the QTranslator object can be re-used.
Consider this (where 'a' is the main instance of the application):
QTranslator translator;
translator.load("mytranslation_cz");
a.installTranslation(&translator);
(...)
a.removeTranslation(&translator)
Now the translator was removed from the application but what happened to the translator object?
In my tests when above code was followed by this again
translator.load("mytranslation_fr");
a.installTranslation(&translator);
it did not do anything in main() and it crashed the application when called from one of the widgets (using pointer to main app).
Therefore I am suspecting that I would need to create one QTranslator object per translation I want to load in the application and that I cannot reuse the QTranslator object. Am I right in this assumption?
And as a side question. Assuming the QTranslator object is untouched by the removeTranslation(), is it possible to simply install it later again like this?
QTranslator translator;
QTranslator translator1;
translator.load("mytranslation_cz");
translator1.load("mytranslation_fr");
a.installTranslation(&translator);
(...)
a.removeTranslation(&translator);
a.installTranslation(&translator1);
(...)
a.removeTranslation(&translator1);
a.installTranslation(&trasnlator); //Will this work?
Thanks for any clarification as I am somewhat confused as to what happens to the QTranslation objects when installing and removing translations from the application and especially if the QTranslation object can be reused for multiple translations somehow on runtime?
QTranslator::load basically in simple sense can be considered as a function that opens a given .qm file, reads in all the translated values and loads it in for a specific language.
Now in general operation you would not want to reuse this for many languages as by "reusing" (even if its allowed) your adding the overhead of parsing this given .qm file for every language every time you switch your UI language, which is just basically an overhead you don't need.
Your assumption of creating a QTranslator for each language is correct. As for your side question, Yes you can also re-use it. Thats the benefit of having individual QTranslator objects per translation. Just call qApp->removeTranslator() with the current translation and then qApp->installTranslator() with the new one. This way you are reusing the loaded translations as and when you please.
The way we structure this is by sub-classing QApplication and adding 2 functions
void Application::CreateTranslators() {
// translators_ is a QMap<QString, QTranslator*>
if (!translators_.isEmpty())
return;
QStringList languages;
languages << "en" << "ar" << "zh";
foreach(QString language, languages) {
QTranslator* translator = new QTranslator(instance());
translator->load(language);
translators_.insert(language, translator);
}
}
Now this function is called at the very start of the application.
2nd function is as following
void Application::SwitchLanguage(QString language) {
// current_translator_ is a QTranslator*
if (current_translator_)
removeTranslator(current_translator_);
current_translator_ = translators_.value(language, nullptr);
if (current_translator_)
installTranslator(current_translator_);
}
That's it. Using the second function you can switch your language at run-time as you please.
Couple things you'll also need to be aware of is changing QTranslator at run-time will update all translations from your .ui file strings marked as translatable automatically, however those set from code will not be. To get that you will have to override QWidget::changeEvent() and then check if the event is of type QEvent::LanguageChange and then set the required strings for that QWidget accordingly (Don't forget the tr() while doing so)

Check if a value registry exists with QSettings

What i'm trying to do is to check if a registry key (NOT VALUE, KEY) exists in the registry. I can't find any way to check that.
Idea?
Using QSettings you can open the key's parent and retrieve the list of its keys. Use the function childGroups() to get the list of keys. It seems that "groups" in qt are keys in Windows registry.
This is the only way I found to check whether a key exists. In this code I look for the key "SearchedKey".
QSettings settings(
"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths",
QSettings::NativeFormat
);
if (settings.childGroups().contains("SearchedKey", Qt::CaseInsensitive))
std::cout << "Key exists" << std::endl;
else
std::cout << "Key doesn't exist" << std::endl;
EDIT:
In 2011 I wrote:
The registry is a Windows concept and doesn't fit Qt's cross-platform notions. You will have to use the Windows API or a C++ wrapper for it.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724875(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/xka57xy4(v=vs.80).aspx
If your needs are more abstract for your application to save and restore its own settings, Qt has a cross-platform design of something called QSettings.
Depending on the nature of the setting and the platform, will store these in the registry or in a file/etc.
But it appears in the answer by #mateuszb that QSettings can open Windows keys if you use QSettings::NativeFormat:
http://doc.qt.io/qt-5/qsettings.html#Format-enum
I'd still suggest that if you are hardcoding something like "HKEY_LOCAL_MACHINE" into your source, that you are not really in the spirit of abstracting your code across platforms in the way that Qt intends. But you apparently can (at least in recent Qt versions) do this without digging beneath Qt and calling the Windows registry APIs.
There is still not a way that I can find for checking for groups. However you can set a key inside a group and check for the existence of that key:
QString groupname = "group";
QString keyname = "/name";
QString name_read = settings.value(groupname + keyname, QString()).toString();
if(name_read == groupname){
...
}else {
// default action
}
This requires an additional key inside of the group called "name" that is set to the name of your group.

Resources