I'm trying to follow this Qt example for adding CSS stylesheet to a QWebEngineView, however, I'm getting this error:
use of undefined type 'QWebEngineScriptCollection'
at the line ui.webEngineView->page()->scripts().insert(script);
What I'm missing? Testing using qt 6.4 Visual Studio 2022, the project can be reproduced by simply adding a QWebEngineView to the ui, and
#include "stdafx.h"
#include "MainWindow.h"
#include <QWebEngineScript>
void MainWindow::insertStyleSheet(const QString& name, const QString& source, bool immediately)
{
QWebEngineScript script;
QString s = QString::fromLatin1("(function() {"\
" css = document.createElement('style');"\
" css.type = 'text/css';"\
" css.id = '%1';"\
" document.head.appendChild(css);"\
" css.innerText = '%2';"\
"})()").arg(name).arg(source.simplified());
if (immediately)
ui.webEngineView->page()->runJavaScript(s, QWebEngineScript::ApplicationWorld);
script.setName(name);
script.setSourceCode(s);
script.setInjectionPoint(QWebEngineScript::DocumentReady);
script.setRunsOnSubFrames(true);
script.setWorldId(QWebEngineScript::ApplicationWorld);
ui.webEngineView->page()->scripts().insert(script);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
}
Fixed it. The correct include is:
#include <QtWebEngineCore/qwebenginescriptcollection.h>
I'm working on a syntax highlighter with Qt and I wanted to add unit tests on it to check if formats are well applied.
But I don't manage to get the block divided by formats. I use QTextBlock and QTextFragment but it's not working while the doc of QTextFragment says :
A text fragment describes a piece of text that is stored with a single character format.
Here is the code in a runnable main.cpp file :
#include <QApplication>
#include <QTextEdit>
#include <QSyntaxHighlighter>
#include <QRegularExpression>
#include <QDebug>
class Highlighter : public QSyntaxHighlighter
{
public:
Highlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{}
protected:
void highlightBlock(const QString& text) override
{
QTextCharFormat classFormat;
classFormat.setFontWeight(QFont::Bold);
QRegularExpression pattern { "\\bclass\\b" };
QRegularExpressionMatchIterator matchIterator = pattern.globalMatch(text);
while (matchIterator.hasNext())
{
QRegularExpressionMatch match = matchIterator.next();
setFormat(match.capturedStart(), match.capturedLength(), classFormat);
}
// ==== TESTS ==== //
qDebug() << "--------------------------------";
QTextDocument *doc = document();
QTextBlock currentBlock = doc->firstBlock();
while (currentBlock.isValid()) {
qDebug() << "BLOCK" << currentBlock.text();
QTextBlockFormat blockFormat = currentBlock.blockFormat();
QTextCharFormat charFormat = currentBlock.charFormat();
QFont font = charFormat.font();
// each QTextBlock holds multiple fragments of text, so iterate over it:
QTextBlock::iterator it;
for (it = currentBlock.begin(); !(it.atEnd()); ++it) {
QTextFragment currentFragment = it.fragment();
if (currentFragment.isValid()) {
// a text fragment also has a char format with font:
QTextCharFormat fragmentCharFormat = currentFragment.charFormat();
QFont fragmentFont = fragmentCharFormat.font();
qDebug() << "FRAGMENT" << currentFragment.text();
}
}
currentBlock = currentBlock.next();
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto *textEdit = new QTextEdit;
auto *highlighter = new Highlighter(textEdit->document());
Q_UNUSED(highlighter);
textEdit->setText("a class for test");
textEdit->show();
return a.exec();
}
And it outputs only one block "a class for test" and one format "a class for test" while the class keyword is in bold.
Thanks for your help !
Ok I found this from the documentation of QSyntaxHighlighter::setFormat :
Note that the document itself remains unmodified by the format set through this function.
The formats applied by the syntax highlighter are not stored in QTextBlock::charFormat but in the additional formats :
QVector<QTextLayout::FormatRange> formats = textEdit->textCursor().block().layout()->formats();
This is a notes program, you write in the textEdit and it saves it using fstream. I am trying to figure out how to load back ALL the words previously typed on the textEdit, right now only the first word loads back. I think it has something to do with the white spaces.
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <fstream>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Setup code
ui->textEdit->setReadOnly(true);
ui->textEdit->append("Select one of the buttons on the left to pick a log");
}
MainWindow::~MainWindow()
{
delete ui;
}
string buttons;
string lastSavedText[] =
{
" ",
" "
};
QString qLastSavedTextHome, qLastSavedTextWork;
This is the first button
void MainWindow::on_homeButton_clicked()
{
// Preparing text edit
ui->textEdit->setReadOnly(false);
ui->textEdit->clear();
ui->textEdit->setOverwriteMode(true);
buttons = "Home";
// Loading previously saved text
ifstream home;
home.open("home.apl");
home >> lastSavedText[0];
home.close();
qLastSavedTextHome = QString::fromStdString(lastSavedText[0]);
ui->textEdit->setPlainText(qLastSavedTextHome);
}
This next button isn't fully developed yet:
void MainWindow::on_workButton_clicked()
{
// Preparing text edit
ui->textEdit->setReadOnly(false);
ui->textEdit->clear();
buttons = "Work";
// Converts textEdit to string
QString textEditText = ui->textEdit->toPlainText();
string plainText = textEditText.toStdString();
}
This is where I convert the textEdit to a string and save the textEdit to a stream:
void MainWindow::on_saveButton_clicked()
{
// Converts textEdit to string
QString textEditText = ui->textEdit->toPlainText();
lastSavedText[0] = textEditText.toStdString();
// Saving files
ofstream home;
home.open("home.apl");
home << lastSavedText[0];
home.close();
}
You are reading only one word in your code:
ifstream home;
home.open("home.apl");
home >> lastSavedText[0]; // Here!!!
home.close();
I'd suggest that you use QFile for reading and writing to file and it'll be more easier to do.
Here's an example:
QFile file { "home.apl" };
if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) )
{
qDebug() << "Could not open file!";
return;
}
const auto& lastSavedText = file.readAll();
file.close();
ui->textEdit->setPlainText( lastSavedText );
You should use Qt features as much you can. You can directly use QString instead of std::string and you won't have to do those conversions.
when i tried my code fir the first time
it was
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QMessageBox"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pix("C:/Users/AMR.EngAmr/Downloads/1561136.jpg");
ui->label_pic->setPixmap(pix);
if(!connOpen())
ui->label_9->setText("فشل الاتصال بقاعدة البيانات");
else
ui->label_9->setText("تم الاتصال بقاعدة البيانات ");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString Name,period,group,Weight,Notes,Notes2,Notes3,pressure;
Name=ui->lineEdit_name->text();
period=ui->lineEdit_2->text();
group=ui->lineEdit_group->text();
Weight=ui->lineEdit_weight->text();
Notes2=ui->lineEdit_notes2->text();
pressure=ui->lineEdit_presure->text();
Notes=ui->lineEdit_notes->text();
Notes3=ui->lineEdit_notes3->text();
if(!connOpen()){
qDebug()<<"Faield to open the database";
return;
}
connOpen();
QSqlQuery qry;
qry.prepare("insert into Patients (Name,period,group,Weight,Notes2,pressure,Notes,Notes3 ) values('"+Name+"','"+period+"''"+group+"','"+Weight+"','"+Notes2+"','"+pressure+"','"+Notes+"''"+Notes3+"')");
if(qry.exec())
{
QMessageBox::information(this,tr("Save"),tr("Saved"));
connClose();
}
else
{
QMessageBox::information(this,tr("error::"),qry.lastError().text());
}
}
and i got error No query Unable to fetch row
and i tried a solution and my code was
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QMessageBox"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QPixmap pix("C:/Users/AMR.EngAmr/Downloads/1561136.jpg");
ui->label_pic->setPixmap(pix);
if(!connOpen())
ui->label_9->setText("فشل الاتصال بقاعدة البيانات");
else
ui->label_9->setText("تم الاتصال بقاعدة البيانات ");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QString Name,period,group,Weight,Notes,Notes2,Notes3,pressure;
Name=ui->lineEdit_name->text();
period=ui->lineEdit_2->text();
group=ui->lineEdit_group->text();
Weight=ui->lineEdit_weight->text();
Notes2=ui->lineEdit_notes2->text();
pressure=ui->lineEdit_presure->text();
Notes=ui->lineEdit_notes->text();
Notes3=ui->lineEdit_notes3->text();
if(!connOpen()){
qDebug()<<"Faield to open the database";
return;
}
connOpen();
QSqlQuery qry;
qry.prepare("insert into Patients (:Name,:period,:group,:Weight,:Notes2,:pressure,:Notes,:Notes3 ) values('"+Name+"','"+period+"''"+group+"','"+Weight+"','"+Notes2+"','"+pressure+"','"+Notes+"''"+Notes3+"')");
qry.bindValue(":Name", Name);
qry.bindValue(":period", period);
qry.bindValue(":group", group);
qry.bindValue(":Weight", Weight);
qry.bindValue(":Notes2", Notes2);
qry.bindValue(":pressure", pressure);
qry.bindValue(":Notes", Notes);
qry.bindValue(":Note3", Notes3);
if(qry.exec())
{
QMessageBox::information(this,tr("Save"),tr("Saved"));
connClose();
}
else
{
QMessageBox::information(this,tr("error::"),qry.lastError().text());
}
}
and i got the error
parameter count mismatch
what is the problem i have to finish it in two days
Looks like you're mixing up your value binding. When you use that, you don't put the values into the query (the very purpose of binding values is avoid that!). This might work, if the column names are correct:
qry.prepare("insert into Patients "
"(Name,period,group,Weight,Notes2,pressure,Notes,Notes3) "
"values(:Name,:period,:group,:Weight,:Notes2,:pressure,:Notes,:Notes3)");
(Note about splitting strings like that, which you probably are not familiar with: in C and C++ writing "foo" "bar" is same as "foobar".)
Also, documentation is your friend. Qt has mostly quite good documentation, and in this case it seems to exactly cover what you are asking.
I have code like below. I have some data in database and I need to create view structure to display it. I don't have big experience in Qt programming, I've made more things in PHP, HTML and CSS. I need to do something like in HTML - when you have a box (for example div) without extra style and you put inside some data this div tag will display all data's inside. But with following code I've got only a part of datas from widgets loaded from file. Behavior of GridLayout in MainWindow is similar to div style="max-width: 200px; max-height: 200px; overflow:hidden". And also Layout elements from children's file has the same behavior...
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "databasemanager.h"
#include "ycexception.h"
#include <QDebug>
#include <QSqlQuery>
#include <QtUiTools>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
createStructureFromDb();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::createStructureFromDb() {
try {
dbManager = new DatabaseManager();
}
catch(YCException e) {
//TODO: show dialog with message
qDebug() << e.what();
exit(-1);
}
QSqlQuery groupsQuery = dbManager->getGroups();
while(groupsQuery.next()) {
Group group;
group.setIdGroup(groupsQuery.value(0).toInt());
group.setName(groupsQuery.value(1).toString());
QUiLoader loader;
QFile file(":/forms/group.ui");
file.open(QFile::ReadOnly);
QWidget *formWidget = loader.load(&file);
file.close();
(formWidget->findChild<QLabel*>("groupName"))->setText(group.getName());
ui->gridLayout->addWidget(formWidget);
QVBoxLayout* groupItems = formWidget->findChild<QVBoxLayout*>("groupItems");
QSqlQuery cardsQuery = dbManager->getGroupCards(group.getIdGroup());
while(cardsQuery.next()) {
Card card;
card.setIdCard(cardsQuery.value(0).toInt());
card.setContent(cardsQuery.value(1).toString());
card.setDueDate(cardsQuery.value(2).toString());
card.setIdGroup(cardsQuery.value(3).toInt());
group.addCard(card);
QFile file(":/forms/card.ui");
QWidget *cardWidget = loader.load(&file);
file.close();
(cardWidget->findChild<QLabel*>("contentLabel"))->setText(card.getContent());
(cardWidget->findChild<QLabel*>("dueDateLabel"))->setText(card.getDueDate());
groupItems->addWidget(cardWidget);
}
groups.insert(group.getIdGroup(), group);
}
ui->label->setText("really long textreally long textreally long textreally long textreally long textreally long textreally long textreally long textreally long textreally long textreally long text");
this->layout()->activate();
}
overflow:hidden is all but explicit for persons like me that have only a very little knowledge of web technologies (but I can google it). But, saying that you want scrollbars is a lot more expressive... I used this page to understand what you want.
So, for what you want: GridLayout is not like html's div. If you want the content of a widget to be scrolled, you have to put the widget in a QScrollArea, and put that scroll area in the cell of the GridLayout that first contained your widget.
More specifically:
overflow:visible : not possible
overflow:hidden : default behavior
overflow:scroll : use QScrollArea
overflow:auto : use QScrollArea
overflow:inherit : possible, but you need to write quite a bit of code to do this. Also, useless in a well-designed interface