QTextEdit doesn't display special characters not available on keyboard - c++

I have to display some special characters like ¼, ½ etc. in a QTextEdit which are not on the QWERTY keyboard.I am able to type these characters in the QTextEdit and also able to paste them. But when I try to programatically set these characters QTextEdit displays an extra character 'Â'.
I do not get this problem while typing and pasting. These characters are typed with some Alt+[code] codes.
I am using Qt 4.8 on Windows 8 64bit.
#include<QtGui>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextEdit t;
t.setPlainText("¼2½ \n"); // QTextEdit displays=> ¼2½
// t.setHtml("¼2½ \n"); // QTextEdit displays=> ¼2½
// t.insertHtml("¼2½ \n"); // QTextEdit displays=> ¼2½
// t.insertPlainText("¼2½ \n"); // QTextEdit displays=> ¼2½
// also tried setHtml() with HTML code which works in Firefox didn't help me
t.show();
return a.exec();
}
How can I put these characters in a QTextEdit programatically without this extra character?

Your source code needs to be written in UTF-8 encoding, and you should use QStringLiteral in Qt 5 or QString::fromUtf8 in Qt 4. You won't have that problem then.
E.g.:
t.setPlainText(QStringLiteral("¼, ½")); // Qt 5
t.setPlainText(QString::fromUtf8("¼, ½")); // Qt 4
Ensure that the editor you're using is set to encode the file as UTF-8, not Latin 1 etc.

Use QTextCodec to display characters in UTF-8 encoding.
#include <QTextCodec>
...
QTextCodec* codec=QTextCodec::codecForName("UTF-8");
// QTextCodec::setCodecForLocale(codec); //if you want everything to be in UTF-8
QTextCodec::setCodecForCStrings(codec);
QApplication a(argc, argv);
...
Or convert characters in place:
t.setPlainText(QObject::trUtf8("¼2½ \n"));

Related

QTextEdit::extraSelections do not work well on Linux/X11 when QTextEdit with wrapped lines has explicitly set small font size

I have recently found a bug in Qt on Linux and reported it to https://bugreports.qt.io/browse/QTBUG-108149 Tested on Ubuntu 20.04 and 22.04 with Qt 5.15.2, 6.2.4 and 6.4, all with X11. I also tested it on Windows 10 and macOS 12.6 and Wayland and these seem to work fine.
Here is a minimal reproducible example. The program should highlight every occurrence of "abcd" in the text edit. However if I set the font size of the text edit to 12 points or smaller, the words in every second line are NOT highlighted. If I do not specify the font size or set font point size of 13 or greater, the highlighting works fine. The same problem seems to be with QPlainTextEdit.
I get this (every second row not highlighted):
This is what I would expect (all rows highlighted):
#include <QApplication>
#include <QTextEdit>
void highlight(QTextEdit *textEdit)
{
QList<QTextEdit::ExtraSelection> highlights;
QString word = "abcd";
QString text = textEdit->toPlainText();
int pos = text.indexOf(word);
while (pos != -1)
{
int endPos = pos + word.length();
auto highlight = QTextEdit::ExtraSelection();
highlight.cursor = QTextCursor(textEdit->document());
highlight.cursor.setPosition(pos);
highlight.cursor.setPosition(endPos, QTextCursor::KeepAnchor);
highlight.format.setForeground(QApplication::palette().color(QPalette::Link));
highlights.append(highlight);
pos = text.indexOf(word, endPos);
}
textEdit->setExtraSelections(highlights);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextEdit w;
// THE NEXT LINES!!!
// If point size 12 or smaller is used, then every second
// row in the text edit is not highlighted.
// If commented out, then everything works fine.
// If point size 13 or greater is used, then everything works fine.
QFont f;
f.setPointSize(12);
w.setFont(f);
w.setPlainText("abcd abcd abcd abcd abcd abcd abcd abcd "
"abcd abcd abcd abcd abcd abcd abcd abcd");
highlight(&w);
w.show();
return a.exec();
}
Any ideas for any workaround until this bug gets officially fixed?

Qt 5.7 \n behavior

In a Qt 5.7 Console Application:
#include <QCoreApplication>
#include <QtDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString s = "MDJ\nTest.\n";
qDebug() << "MDJ\nTest.\n";
qDebug() << s;
/* Prints:
MDJ
Test.
MDJ\nTest.\n
*/
return a.exec();
}
i.e. the \n works as expected in a direct debug print, but is treated as just two plain characters when debug printing a (supposedly identical content) variable.
I'm encountering similar problems in Qt 5.7 Widget Applications as well.
I've searched the documentation, stackoverflow, and Qt Centre and I've been unable to discover what I'm doing wrong.
Could somebody please point me to a solution for this?
The docs give you hints:
<< QString()
Normally, QDebug prints the string inside quotes and transforms non-printable characters to their Unicode values (\u1234).
To print non-printable characters without transformation, enable the noquote() functionality. Note that some QDebug backends might not be 8-bit clean.
vs.
<< const char*
Writes the '\0'-terminated string, s, to the stream and returns a reference to the stream. The string is never quoted nor transformed to the output, but note that some QDebug backends might not be 8-bit clean.
Solution: qDebug().noquote() << "some\nspecial\nchars\n\tincluded"

Printing qByteArray through qDebug

#include <QCoreApplication>
#include <QByteArray>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QByteArray dataReceivedFromSerialPort;
dataReceivedFromSerialPort.push_back(0x0A);
dataReceivedFromSerialPort.push_back(0x0B);
dataReceivedFromSerialPort.push_back(0x0C);
dataReceivedFromSerialPort.push_back(0x0D);
dataReceivedFromSerialPort.push_back(0x0E);
dataReceivedFromSerialPort.push_back(0x0F);
dataReceivedFromSerialPort.push_back(0x07);
dataReceivedFromSerialPort.push_back(0x02);
dataReceivedFromSerialPort.push_back(0x01);
dataReceivedFromSerialPort.push_back(0x02);
qDebug() << "tostr: " << dataReceivedFromSerialPort.toStdString().c_str();
return a.exec();
}
The above does not print any value. It doesn't print anything beyond "tostr: ". If I store 0x0A in uchar and then push it in qByteArray then this problem disappears.
What can I do print it in its current form?
Because the bytes you give are, in many encodings, various control characters (newlines, carriage returns, etc.). Going through std::string and char* means the bytes will be sent as they are to the terminal, and thus displayed that way (either not at all, or as various types of whitespace).
You can try to instead do one of these, depending on what you want:
qDebug() << dataFromSerialPort; // prints "\n\x0B\f\r\x0E\x0F\x07\x02\x01\x02"
qDebug() << QString::fromLatin1(dataFromSerialPort); // prints "\n\u000B\f\r\u000E\u000F\u0007\u0002\u0001\u0002"
qDebug() << dataFromSerialPort.toHex(); // "0a0b0c0d0e0f07020102"
qDebug() << qPrintable(dataFromSerialPort); // same as toStdString().c_str(), but IMO more readable.
These print the bytes in various escape sequences (QString uses unicode, that's why you see \u instead of \x there), as a readable hexadecimal representation as well "as is".
QDebug does special formatting for many known types, like QString and QByteArray, that is why the first three examples above print with quotes and write out the escape sequences (it's for debugging after all). qPrintable, which works very similar to toStdString().c_str() returns a char*, which QDebug does not format in any special way, which is why you get whitespace as the output (this is the same behaviour as std::cout and friends).

how to read stdin to end in qt?

I have a qt-app which can be invoked with:
cat bla.bin | myapp
Whats the easiest way to read the entire input (stdin) into a QByteArray on Win,Mac and Linux?
I tired several things, but none of them seems to work (on windows):
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QByteArray content;
//---Test 1: hangs forever, reads 0
while(!std::cin.eof()) {
char arr[1024];
int s = std::cin.readsome(arr,sizeof(arr));
content.append(arr,s);
}
//---Test 2: Runs into timeout
QFile in;
if(!in.open(stdin,QFile::ReadOnly|QFile::Unbuffered)) {
qDebug() << in.errorString();
}
while (in.waitForReadyRead(1000)) {
content+=in.readAll();
}
in.close();
return app.exec();
}
Am I having a Event-Loop Problem or shouldn't it work without?
The primary problem of actually reading from stdin stems from using readsome. readsome is generally not used to read from files (including stdin). Readsome is generally used for binary data on asynchronous sources. Technically speaking eof doesn't get set with readsome. read is different in that regard as it will set eof accordingly. There is an SO question/answer here that may be of interest. If you are supporting Linux and Windows and reading stdin, you have to be aware that on Windows stdin isn't opened in binary mode (neither is stdout). On Windows you would have to use _setmode on stdin. One way to do this is with #ifdefs using Q_OS_WIN32. Using QFile doesn't resolve this issue.
In the code you are trying to create it doesn't appear you are interested in actually having an event loop. You can still use QT objects like QByteArray without an event loop. In your code you read data in from stdin (cin) and then you executed return app.exec(); which put your console application into a loop waiting for events. You didn't add any events to the QT Event queue prior to app.exec(); so effectively the only thing you can do is end your application with control-c. If no event loop is needed then code like this should suffice:
#include <QCoreApplication>
#include <iostream>
#ifdef Q_OS_WIN32
#include <fcntl.h>
#include <io.h>
#endif
int main()
{
QByteArray content;
#ifdef Q_OS_WIN32
_setmode(_fileno(stdin), _O_BINARY);
#endif
while(!std::cin.eof()) {
char arr[1024];
std::cin.read(arr,sizeof(arr));
int s = std::cin.gcount();
content.append(arr,s);
}
}
Notice how we used a QByteArray but didn't have a QCoreApplication app(argc, argv); and a call to app.exec();

Increasing spaces between words,ordering words in columns

Is there possibility to easily increase spaces between words in QTextEdit?
My only idea is to set space key event to insert more whitespaces, but i would better like some setting parameters solution?
Is there way to set words in columns in text edit. What I mean:
first word wordabc abcd
second word worda egdsa
third word wordb dafdd
With this I have no idea for now.
The QTextEdit can render html, so you could use table elements to achieve what you want.
#include <QtGui/QApplication>
#include <QtGui/QTextEdit>
int main(int argc, char *argv[])
{
QString html = "<html><body><table>";
html += "<tr><td>first word</td><td>wordabc</td><td>abcd</td></tr>";
html += "<tr><td>second word</td><td>worda</td><td>egdsa</td></tr>";
html += "<tr><td>third word</td><td>wordb</td><td>dafdd</td></tr>";
html += "</table></body></html>";
QApplication app(argc, argv);
QTextEdit textEdit;
textEdit.setHtml(html);
textEdit.show();
return app.exec();
}
You could also apply styling to the table for example by adding the width attribute to the td tag to push columns apart from each other.
You can apply QTextCharFormat to your text and use QTextCharFormat::setFontWordSpacing ( qreal spacing )