Qt QTextEdit line numbers - c++

I'm working on a code editor for GLSL in Qt and I'm having problems with showing the line numbers of a QTextEdit. I undestand the example from Qt Code Editor Example but this part
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + (int) blockBoundingRect(block).height();
doesn't really combine well with a QTextEdit given the fact that I don't have the firstBisibleBlock, blockBoundingGeometry and blockBoundingRect methods. I know the blocks are kept in a QTextDocument but that class doesn't have these methods either.
I tried searching for an example but every time someone asks this question he is directed to that same link.
Could anyone help me?
Thanks

The example uses QPlainTextEdit and accesses firstVisibleBlock() etc protected functions.
Take a look at the source code for QPlainTextEdit and see what IT does to implement these functions. It looks as though they are implemented in terms of the document (at least firstVisibleBlock() does).
Alternatively, copy the example and derive from QPlainTextEdit yourself and don't use QTextEdit.

Related

QT : how to synchronize QtableViews in layouts?

i'm working on a Qt project with an interface and i'm using four QTableViews and for some reason, the last one is not following the others when i stretch the windows. the 4 tableviews have the exact same parameters. they are in layouts, along with other items on the interface. i set the MaximumWidth of my tableview like this :
int hHeaderWidth = ui->tableCSB_Right->verticalHeader()->width();
int rowWidth = ui->tableErr_Right->columnWidth(0);
int tableWidth = (nbOfAnt/2)*rowWidth + hHeaderWidth;
ui->tableErr_Right->setMaximumWidth(tableWidth);
ui->tableErr_left->setMaximumWidth(tableWidth);
ui->tableCSB_Right->setMaximumWidth(tableWidth);
ui->tableCSB_Left->setMaximumWidth(tableWidth);
ui->tableLeft_Coupling->setMaximumWidth(tableWidth);
ui->tableRight_Coupling->setMaximumWidth(tableWidth);
and here's what i get when i launch my program and when i stretch the window:
as you can see the last qtableview goes way farther and the other ones along with its QPushButton and labels. i dont get why does it behave like this. has anyone dealt with this problem ?
thank you in advance

QSizePolicy::Minimum doesn't minimalize qwidget

I want to have the following layout in a Qt-C++ project: A VBoxLayout with in it two QTextEdits underneath each other. The top one should shrink to have the minimal size: 1 line of text if there's one line in it, bigger if there's more. The bottom one should take the remaining space in the window.
I now have the following code in the constructor of my mainwindow (which extends QMainWindow):
QWidget *mainpanewidget = new QWidget(this);
QVBoxLayout *mainpane = new QVBoxLayout(mainpanewidget);
this->setCentralWidget(mainpanewidget);
QTextEdit *firsttext = new QTextEdit(this);
firsttext->setText("first text");
QTextEdit *secondtext = new QTextEdit(this);
secondtext->setText("second text");
//first try: use sizepolicies
firsttext->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
secondtext->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
//second try: explicitely set minimum size to something small
firsttext->setMinimumHeight(10);
firsttext->setMinimumWidth(10);
//3th try: stretch factors
mainpane->setStretchFactor(firsttext,0);
mainpane->setStretchFactor(secondtext,1);
//4th try: size policy of surrounding layout
mainpanewidget->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
mainpane->addWidget(firsttext);
mainpane->addWidget(secondtext);
mainpane->update();
With this code the second QTextEdit does become larger than the first one, but the first one seems to think it's minimal size should be 192 pixels (14 lines), which is far above it's real necessary number of lines: 1. This is the size given by sizehint, instead of minimalheight. Unfortunately there doesn't seem to be a way to adapt sizehint without subclassing QTextEdit.
I have tried different things, as can be seen in the above code, to come up with one minimal QTextEdit and one expanding. The only one that works is to set the maximumheight of the first QTextEdit, which is something I don't want to hardcode as the text in it may be larger than some limit I hardcode now. Plus hardcoding limits is not very good coding practice.
As I want to use similar sizing for different qwidgets in my application (QTextEdit, labels, buttons,...) I would prefer to not have to use inheritance, as this would bring in a lot of extra classes which all change but a single thing of their parent class.
I work in Qt 5.7.0.
Note: there seem to be a lot of questions regarding qsizepolicy and resizing in Qt. If I missed a duplicate of this question you are free to link it and close this one.

Reordering MFC control IDs automatically

I've got a pretty old MFC application that's been touched by many people over the years (most of them probably not even CS guys) and it follows, what I like to call the "anarchy design pattern."
Anyway, one of the dialogs has a series of 56 vertical sliders and check boxes. However, there are additional sliders and checkboxes on the dialog as shown below.
Now, the problem is that the additional sliders and checkboxes take on IDs that are in sequence with the slider/checkbox series of the dialog. My task is to add more sliders and checkboxes to the series (in the blank space in the Slider Control group box) Unfortunately, since IDC_SLIDER57 through IDC_SLIDER61 are already in the dialog (same goes for the checkboxes), existing code, such as the snippet below will break:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
Is there a better way to modify the resource file without doing it manually? I've seen a third party tool called ResOrg that looks like it'll help do what I want, but the software is a bit pricey, especially since I'll only use it once. I guess I can give the demo a try, but the limitations might restrict me.
FYI, I'm using Visual C++ 6.0 (yes...I know, don't laugh, it's being forced upon me).
Instead of writing:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
you could write:
pVSlider = (CSliderCtrl *)GetDlgItem(GetSliderID(i));
where GetSlider is a function that returns the id of slider number i.
GetSlider function
int GetSliderID(int nslider)
{
static int sliderids[] = {IDC_SLIDER1, IDC_SLIDER2, IDC_SLIDER3, .... IDC_SLIDERn};
ASSERT(nslider < _countof(sliderids));
return sliderids[nslider];
}
With this method the IDC_SLIDERn symbols dont need to have sequential values.

QTextEdit change font of individual paragraph/block

Using a QTextEdit, I need to change the font attributes of each paragraph individually. This is similar to how many word processors change the font of a paragraph when the user select a style from a menu (not a specific formatting).
Ideally, I would like to apply a QTextCharFormat (or equivalent) to a block (paragraph) just before it is laid out and rendered, but I would prefer that no font attribute be actually inserted in the text, as I don't want this information in the file but I need to preserve any bold/italic/underline attributes that the user might have set to words within paragraphs (I intend to save the needed information in a QTextBlock::userData). However, I can't figure where I would need to insert a function to perform this task.
I figured I could not change the QTextCharFormat of a paragraph from either QTextBlock nor QTextCursor as this only applies to new blocks, it doesn't affect blocks with existing text.
I checked out QTextLayout but I don't think my answer is there.
I have been looking for a solution to this problem for a few days now. I would be really gracious for any pointer in the right direction.
I have years of experience with C++, but I'm somewhat new to Qt. Using Qt 4.8.
Edit:
I added emphasize (bold) above to an important part of what I'm trying to do. In other word, what I'd really like to do is be able to apply the font attributes to the block of text (perhaps a temporary copy) just before it is displayed. I'm totally comfortable with deriving and modifying (even reimplement) any class that I need to in order to achieve that goal, but I need to be pointed to the right direction as to what I actually need to change. As a last resort, I could also modify some Qt class directly if that is necessary for the task, but again would need to know what class I need to touch. I hope this is clearer. I find it difficult to explain this without being allowed to tell you what the application will do exactly.
[Required Libraries]
#include <QTextEdit> // not needed if using the designer
#include <QTextDocument>
#include <QTextBlock>
#include <QTextCursor>
[Strategy]
QTextDocument
I need it to manage the blocks. The function QTextDocument::findBlockByNumber is quite handy to locate the previous blocks, and I think it is what you are after.
QTextBlock
Container for block texts. A nice and handy class.
QTextCursor
Surprisingly, there is no format-setter in QTextBlock class. Therefore I use QTextCursor as a workaround since there are four format-setters in this class.
[Code for formatting]
// For block management
QTextDocument *doc = new QTextDocument(this);
ui->textEdit->setDocument(doc); // from QTextEdit created by the Designer
//-------------------------------------------------
// Locate the 1st block
QTextBlock block = doc->findBlockByNumber(0);
// Initiate a copy of cursor on the block
// Notice: it won't change any cursor behavior of the text editor, since it
// just another copy of cursor, and it's "invisible" from the editor.
QTextCursor cursor(block);
// Set background color
QTextBlockFormat blockFormat = cursor.blockFormat();
blockFormat.setBackground(QColor(Qt::yellow));
cursor.setBlockFormat(blockFormat);
// Set font
for (QTextBlock::iterator it = cursor.block().begin(); !(it.atEnd()); ++it)
{
QTextCharFormat charFormat = it.fragment().charFormat();
charFormat.setFont(QFont("Times", 15, QFont::Bold));
QTextCursor tempCursor = cursor;
tempCursor.setPosition(it.fragment().position());
tempCursor.setPosition(it.fragment().position() + it.fragment().length(), QTextCursor::KeepAnchor);
tempCursor.setCharFormat(charFormat);
}
Reference:
How to change current line format in QTextEdit without selection?
[DEMO]
Building Environment: Qt 4.8 + MSVC2010 compiler + Windows 7 32 bit
The demo is just for showing the concept of setting the format on a specific block.
Plain text input
Format 1 (notice that it won't bother the current cursor in view)
Format 2
You can use QTextCursor to modify existing blocks.
Just get a cursor and move it to the beginning of the block. Then move it with anchor to create a selection.
Set this cursor to be the current cursor for the text edit and apply your changes.
QTextEdit accepts HTML so all you have to do is to format your paragraphs as HTML. See example below:
QString text = "<p><b>Paragraph 1</b></p><p><i>Paragraph 2</i></p>";
QTextCursor cursor = ui->textEdit->textCursor();
cursor.insertHtml(text);
That will create something like this:
Paragraph 1
Paragraph 2
Having said that, there is only a subset of HTML that is supported in Qt. See Supported HTML Subset

Taking data from a Dialog in Qt and using it in a Ui

So I'm making a text editor using Qt and right now I have a button that opens a dialog called "Format text". I want it to work kind of like the dialog in notepad called "font" where you select a few text attributes from some drop down lists and it shows you what your text will look like. Right now I have it working where you can select the font style, font color, and font size and hit preview and it shows you in a box in the dialog what your text will look like. However, I have a button called "okay" which is supposed to change the highlighted text or the text you are about to type, but I can't figure out how to display those changes on the main window. The .ui files are private and a lot of the already made functions and pointers are the same in every ui file so if I change the ui file to pubic I have to change a whole bunch of things. Can anyway give me a simple answer? I'm trying to do this with as little confusion as possible. More coding and less confusion is better than less coding and more confusion for someone of my skill level. Sorry that this is all one giant paragraph and that I didn't provide any code, but I didn't think the code was necessary, however if you do need some of the code i'd be happy to share it.
Thank you for your help and your time. I hope you all have a nice evening.
QDialog have a signal called finished(), you can connect this signal with your slot. To accomplish your work, pass a QSettings or for simplicity QStringList to dialog settings (responsible for changing font, color ...), the QStringList will save user defined settings, after closing the dialog, iterate through QStringList member to alert Main window.
A pseudo code will look like this
Class Editor:
Editor::Editor()
{
TextSettings textSettings;
textSettings.setSettings(settings); // settings is a member
connect(textSettings, &finished(int)), this, SLOT(alertEditor(int)))
}
Editor::alertEditor(int s)
{
if(s == 0)
{
for (int i = 0; i < settings.size(); ++i)
settings.at(i).toLocal8Bit().constData(); // extract various user settings
}
}
Class TextSettings:
TextSettings::TextSettings(QStringList settings)
{
settings << ui->combobox->currentItem(); // font name as example
}