QScintilla how to continously get cursor position in textEdit widget? - c++

I'm working on a source code editor in C++, using Qt5 and QScintilla as framework. In this project, I want to continously show the row and column of the text cursor (cursor position), so I need a SIGNAL that emmits whenever the text cursor is moved. According to QScintilla docs, cursorPositionChanged(int line, int index) emmits the wanted signal whenever the cursor is moved, so I guess this must be the method that I need? This is what I did so far:
// notify if cursor position changed
connect(textEdit, SIGNAL(cursorPositionChanged(int line, int index)), this, SLOT(showCurrendCursorPosition()));
my code compiles and the editor window shows up as wanted, but unfortunately, I got the warning:
QObject::connect: No such signal QsciScintilla::cursorPositionChanged(int line, int index)
Can someone please provide me with a QScintilla C++ or Python example showing how to continously get and display the current cursor position?
Complete source code is hosted here:
https://github.com/mbergmann-sh/qAmigaED
Thanks for any hints!

The problem is caused by the old syntax of connection that is verified in runtime, in addition that old syntax has as another problem that have to match the signatures. In your case the solution is to use the new connection syntax that does not have the problems you mention.
connect(textEdit, &QTextEdit::cursorPositionChanged, this, &MainWindow::showCurrendCursorPosition);
For more information you can check:
https://wiki.qt.io/New_Signal_Slot_Syntax

Thanks, eyllanesc, your solution works fine!
I also found a working solution myself, just had to remove the named vars from the connection call:
// notify if cursor position changed
connect(textEdit, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(showCurrendCursorPosition()));
...
//
// show current cursor position and display
// line and row in app's status bar
//
void MainWindow::showCurrendCursorPosition()
{
int line, index;
qDebug() << "Cursor position has changed!";
textEdit->getCursorPosition(&line, &index);
qDebug() << "X: " << line << ", Y: " << index;
}
This topic is SOLVED.

Related

Data does not get reflected in real time in Qt TexttEdit widget

I am trying to scan files and its sub directory , the code from Qt Examples works absolutely fine and displays data with QDebug() .
However when i try to it.next() data to a Qlable or textEdit widget , it doesn't show the data in realtime. The data is reflected after the it.hasNext() gets completed. I want to show real time scanning status in the textedit box - Self is new to Qt.
How to show the status for the file being scanned in real time, in the Qt textEdit widget ?
Code is given below .
void MainWindow::findFilesRecursively(QDir rootDir) {
QDirIterator it(rootDir, QDirIterator::Subdirectories);
while(it.hasNext()) {
qDebug() << it.next();
// ui->textEdit->append(it.next()); <<<<<<---- This is note getting updated realtime,
Data get populated after the scan in complted.
}
}
Error
enter image description here
This may or may not be your problem, but do you understand what your code is trying to do?
Your debug statement calls it->next(). You then in your commented-out code call it->next() a second time. If your directory only contains a single file, you've already dumped it. The debug statement eats it.
What you need instead:
QString fName = it->next();
qDebug() << fName;
ui->textEdit->append(fName);
I'm not absolutely positive this is your problem, because I don't know if you commented out your qDebug when you ran it or how big your directory is. There might be something else going on.

Display QProcess output in another window

I'm using the QT Creator on Ubuntu.
I have GUI with a mainwindow and another window called "progress".
Upon clicking a button the QProcess starts and executes an rsync command which copies a folder into a specific directory. I created a textbrowser which reads the output from the rsync command. Also clicking the button causes the "progress" window to pop up.
So far so so good, now my problem.
Instead of showing the rsync output in my mainwindow i want it to be in progress.
I've tried several methods to get the QProcess into the progress via connect but that doesn't seem to work.
mainwindow.cpp
void MainWindow::on_pushButton_clicked()
{
if (ui->checkBox->isChecked()
)
m_time ="-t";
QObject parent;
m_myProcess = new QProcess();
connect(m_myProcess, SIGNAL(readyReadStandardOutput()),this, SLOT(printOutput()));
QString program = "/usr/bin/rsync";
arguments << "-r" << m_time << "-v" <<"--progress" <<"-s"
<< m_dir
<< m_dir2;
m_myProcess->start(program, arguments);
}
progress.cpp
void Progress::printOutput()
{
ui->textBrowser->setPlainText(m_myProcess->readAllStandardOutput());
}
I know it's pretty messy iv'e tried alot of things and haven't cleaned the code yet also I'm pretty new to c++.
My goal was to send the QProcess (m_myProcess) to progress via connect but that didn't seem to work.
Can you send commands like readyReadAllStandardOutput via connect to other windows (I don't know the right term )?
Am I doing a mistake or is there just another way to get the output to my progress window ?
m_myProcess is a member of the class MainWindow and you haven't made it visible to the class Progress. That's why you have the compilation error
m_myProcess was not declared in this scope
What you could do:
Redirect standard error of m_myProcess to standard output, such that you also print what is sent to standard error (unless you want to do something else with it). Using
m_myProcess.setProcessChannelMode(QProcess::MergedChannels);
Make the process object available outside MainWindow
QProcess* MainWindow::getProcess()
{
return m_myProcess;
}
Read the process output line by line in Progress. It needs to be saved in a buffer because readAllStandardOutput() only return the data which has been written since the last read.
... // somewhere
connect(window->getProcess(), SIGNAL(readyReadStandardOutput()), this, SLOT(printOutput())
...
void Progress::printOutput(){
//bigbuffer is member
bigbuffer.append(myProcess->readAllStandardOutput();)
ui->textBrowser->setPlainText(bigbuffer);
}

How to show list of strings in QT at run time?

I have a list of strings during run time.
Any one help me to display these strings in QWidget. When I right click that string I need to have a option show index that will show index of that string in QMessageBox.
If it is possible means give some technical guidance.
Thank you.
OK, so let us start with the design for your use case...
I would recommend using a QListWidget for a list. Each string could be a separate item.
You could show a popup for right click, but if it only has the show index action, it does not really make that much sense on its own. You could just show the messagebox with that index right away.
I would write something like this below:
MyClass::MyClass(QObject *parent)
: QObject(parent)
, m_listWidget(new QListWidget(this))
{
QStringList myStringList = QStringList() << "foo" << "bar" << "baz";
m_listWidget->addItems(myStringList);
// Set up your action with the popup for right click if needed
// and connect to the "triggered" signal of the particular action
connect(listWidget, SIGNAL(itemClicked(QListWidgetItem * item)), SLOT(showMessageBox(QListWidgetItem * item)));
...
}
void MyClass::showMessageBox(QListWidgetItem * item)
{
Q_UNUSED(item)
QMessageBox messageBox;
messageBox.setText(m_listWidget->currentRow());
messageBox.exec();
}
If you have more actions for the right click, you could use a popup dialog, yes, with several actions placed onto, but so far, that does not seem to be the use case in here.

WT widget not updating in boost thread

I have run into an interesting problem with WT, I have solved it, but I do not understand WHY my solution solved the problem. I've dug through WT documentation for the widgets and have come up empty handed so far, so maybe someone who knows more about WT can help me out here.
Anyway, the problem is with a WComboBox widget in a boost thread not updating it's data when clicked on and having it's selection changed.
I created a boost thread in a class
class MyConsole: public WApplication
{
private:
boost::shared_ptr<boost::thread> _thread;
WComboBox* _combo_box;
bool running;
//Thread function
void my_thread(Wt::WApplication *app);
}
Then I fill the combo box with data, lets use "foo" and "goya" as the 2 entries. I made a function for the thread, and put a loop into it.
void MyConsole::my_thread(Wt::WApplication *app)
{
while(running)
{
std::string test;
Wt::WApplication::UpdateLock lock(app);
if(lock)
{
test = _combo_box->valueText().narrow();
}
if (strcmp("foo", test.c_str()) == 0)
{
cout << "we got foo" << endl;
}
else if (strcmp("goya", test.c_str()) == 0)
{
cout << "we got goya" << endl;
}
}
}
Without changing the initial selection of the combo box, the above code always enters the foo if statement, which is expected. However, when I change the selection of the _combo_box to "goya" the above code still enters the "foo" if statement, which is very unexpected. Investigating the matter further such as printing out the current index of the combo box before the if statement showed me that it is always 0 and never gets incremented when the selection changes.
The way I fixed it was by connecting the combo box changed() signal to a do nothing function that I added to the class.
class MyConsole: public WApplication
{
private:
...
void WWidgetForceUpdate(void)
{
}
...
}
...
_combo_box->changed().connect(this, &MyConsole::WWidgetForceUpdate);
With the addition of that function call when the selection changes, the "foo" and "goya" if statements worked properly, and printing out the current index of the combo box before the if statement confirmed that the index was now changing.
Why did connecting the changed() signal to a do nothing function remedy the situation? I am sure there is a bigger problem that I am not seeing here :(
Any help would be much appreciated.
Wt sends changes from the browser to the server when events happen. If your program is not interested in an event, this synchronisation will not take place (otherwise synchronisation would take place on every character of text you enter in an input box, on every mose movement, .... even if your application is not doing anything with it). Nothing connected to changed() means that nothing is interested in that specific event, and the browser will not notify the server when it happens.
Any event that is being listened upon will send all changes of all widgets to the server, so that the full widget tree is synchronised. So if you have a button with clicked() listener, and a combobox without a changed() listener, the state of the combobox will still be updated in the widget tree when you click the button.
There is however a bug in your code: you cannot just access the widget tree from a random thread without grabbing the update lock (WApplication::UpdateLock).

Qt - Detect item information change in QListView

I have a QListView which is connected to a QStandardItemModel. How do I detect any information change in the model or the QListView? I tried the Signals and Slots with the itemChanged() for the model but it seems to crash the whole program.
Qbject::connect(bugModel, SIGNAL(itemChanged(QStandardItem*)), this, SLOT(bugInfoChanged()));
That is the code I'm using to connect the Signal. the function bugInfoChanged() just runs a qDebug() that says "Changed". But when I start the program, it shows a crash error.
When I comment this line (//QObj...) then the crash doesn't occur, but again when I remove the comment it does crash. I have this in my "Private Slots" area:
void bugInfoChanged();
and it's like this in the cpp:
void MainWindow::bugInfoChanged()
{
qDebug() << "Changed";
}
I have no clue as to what causes the crash :/
I fixed it myself. Turns out if I place the connecting code in a function where the list is populated, it works just fine. It used to crash because the list didn't have any item at the moment when the App started.