I want to insert a check box in a html using QT. Currently, I can generate a html using QTextEdit, QTextCursor. But I have no idea how to insert a check box.
If somebody has implement this problem, please tell me some details.
ZhQ
Fortunately, I have found the solution. The code using to generate the html file is:
QTextEdit * editor = new QTextEdit();
editor->setAcceptRichText(true);
QTextCursor cursor(editor->textCursor());
cursor.insertText("hello, qt html!!");
cursor.insertBlock();
QTextDocument * pDoc = editor->document();
QString strResult = pDoc->toHtml();
QFile file("test.html");
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
return 0;
}
QTextStream out(&file);
out.setCodec("utf-8");
out << strResult;
file.close();
In order to insert the check box, the following code is workable:
out << "<input type='checkbox'>";
And the following code will insert a radio into to a html:
out << "<input type='radio', name='type1'>";
out << "<input type='radio', name='type1'>";
In the all, the whole code is:
QTextEdit * editor = new QTextEdit();
editor->setAcceptRichText(true);
QTextCursor cursor(editor->textCursor());
cursor.insertText("hello, qt html!!");
cursor.insertBlock();
QTextDocument * pDoc = editor->document();
QString strResult = pDoc->toHtml();
QFile file("test.html");
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
return 0;
}
QTextStream out(&file);
out.setCodec("utf-8");
out << strResult;
out << "<input type='checkbox'>";
out << "<input type='radio', name='type1'>";
out << "<input type='radio', name='type1'>";
file.close();
zhq
Related
I have written a QT5 application that creates a monthly rota/timesheet based on various inputs. It generates a csv file that I can use excel to read and print. I can use libreoffice to print this onto a single A4 sheet.
However what I would really like to do is to use qt to print the table directly to the printer.
I am afraid that I am confused as to how best to go about trying to achieve this. I have used html with a QTextDocument to successfully print out the rota/timesheet. However the result ends up on two pages rather then one. I print it out in landscape mode. I think that it would be good to scale the height of the document down to fit on one page.
void ViewEditRotaDialog::m_printButtonSlot()
{
QString strStream;
QTextStream out(&strStream);
const int rowCount = m_tableWidget->rowCount();
const int columnCount = m_tableWidget->columnCount();
out << "<html>\n"
"<head>\n"
"<meta Content=\"Text/html; charset=Windows-1251\">\n"
<< QString("<title>%1</title>\n").arg("ROTA")
<< "</head>\n"
"<body bgcolor=#ffffff link=#5000A0>\n"
"<table border=1 cellspacing=0 cellpadding=2>\n";
// headers
out << "<thead><tr bgcolor=#f0f0f0>";
for (int column = 0; column < columnCount; column++)
out << QString("<th>%1</th>").
arg(m_tableWidget->horizontalHeaderItem(column)->text());
out << "</tr></thead>\n";
// data table
for (int row = 0; row < rowCount; row++)
{
out << "<tr>";
for (int column = 0; column < columnCount; column++)
{
QString data
m_tableWidget->item(row,column)->text().simplified();
out << QString("<td bkcolor=0>%1</td>").
arg((!data.isEmpty()) ? data : QString(" "));
}
out << "</tr>\n";
}
out << "</table>\n"
"</body>\n"
"</html>\n";
QTextDocument *document = new QTextDocument();
document->setHtml(strStream);
QPrinter printer(QPrinter::HighResolution);
printer.setOrientation(QPrinter::Landscape);
printer.setPageMargins(0.1,0.1,0.1,0.1,QPrinter::Millimeter);
printer.setFullPage(true);
QPrintDialog *dialog = new QPrintDialog(&printer, NULL);
if (dialog->exec() != QDialog::Accepted)
return;
document->print(&printer);
delete document;
}
I have seen other examples using QPainter and trying to scale the output.
Should I be doing this and using drawcontents() or should I be using a completely different method?
I decided to have a play with using painter and drawContents(). I was pleased that I could get it to do what I needed with minimum effort. I dont yet fully understand the details of how this works, but I will look into it in more detail later. It might be that I will need to enhance this, but it looks very good for what I need. Simply put it looks like I just needed to change the scales to make it do what I required. Not ever having used QT before to do printing I did'nt really know how best to do this. But I am happy with the result.
I replaced the code under
QTextDocument *document = new QTextDocument();
with
`
document->setHtml(strStream);
QPrinter printer(QPrinter::HighResolution);
printer.setPaperSize(QPrinter::A4);
printer.setOrientation(QPrinter::Landscape);
printer.setPageMargins(0.1,0.1,0.1,0.1,QPrinter::Millimeter);
printer.setFullPage(true);
QPrintDialog *dialog = new QPrintDialog(&printer, NULL);
if (dialog->exec() != QDialog::Accepted)
return;
QPainter painter;
painter.begin(&printer);
double xscale = printer.pageRect().width() / document->size().width();
double yscale = printer.pageRect().height() / document->size().height();
painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
printer.paperRect().y() + printer.pageRect().height() / 2);
painter.scale(xscale, yscale);
painter.translate(-document->size().width() / 2,
-document->size().height() / 2);
document->drawContents(&painter);
painter.end();
delete document;
}`
This may not be the best answer, but it works so far.
For the past few days I've been tinkering with the Arduino IDE + ESP32 Core and a DOIT ESP32 DEVKITV1.
I want to make a web interface using Hieromon's AutoConnect and I've scrolling through his API's libraries and the thing that I didn't understand at all was the "merging" of HTML and C++.
/**< Common html document header. */
const char AutoConnect::_ELM_HTML_HEAD[] PROGMEM = {
"<!DOCTYPE html>"
"<html>"
"<head>"
"<meta charset=\"UTF-8\" name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
};
/**< LuxBar menu element. */
const char AutoConnect::_ELM_MENU[] PROGMEM = {
"<header id=\"luxbar\" class=\"luxbar-fixed\">"
"<input type=\"checkbox\" class=\"luxbar-checkbox\" id=\"luxbar-checkbox\"/>"
"<div class=\"luxbar-menu luxbar-menu-right luxbar-menu-material-bluegrey\">"
"<ul class=\"luxbar-navigation\">"
"<li class=\"luxbar-header\">"
"MENU_TITLE"
"<label class=\"luxbar-hamburger luxbar-hamburger-doublespin\" id=\"luxbar-hamburger\" for=\"luxbar-checkbox\"><span></span></label>"
"</li>"
"<li class=\"luxbar-item\">Configure new AP</li>"
"<li class=\"luxbar-item\">Open SSIDs</li>"
"<li class=\"luxbar-item\">Disconnect</li>"
"<li class=\"luxbar-item\" id=\"reset\">Reset...</li>"
"<li class=\"luxbar-item\">HOME</li>"
"</ul>"
"</div>"
"<div class=\"lap\" id=\"rdlg\">"
"<div class=\"modal_button\"><h2>RESET</h2></div>"
"</div>"
"</header>"
};
/**< The 404 page content. */
const char AutoConnect::_PAGE_404[] PROGMEM = {
"{{HEAD}}"
"<title>Page not found</title>"
"</head>"
"<body>"
"404 Not found"
"</body>"
"</html>"
};
/**< The page that started the reset. */
const char AutoConnect::_PAGE_RESETTING[] PROGMEM = {
"{{HEAD}}"
"<meta http-equiv=\"refresh\" content=\"{{UPTIME}};URL=" AUTOCONNECT_URI "\">"
"<title>AutoConnect resetting</title>"
"</head>"
"<body>"
"<h2>{{RESET}}</h2>"
"</body>"
"</html>"
};
As you can see, this is the declaration of multiple HTML pages.
It starts with:
const char AutoConnect::_ELM_HTML_HEAD[] PROGMEM = {
"<!DOCTYPE html>"
"<html>"
"<head>"
"<meta charset=\"UTF-8\" name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
};
He opened the html and head tag there and never closed them.
He then continued to "making another HTML page"
const char AutoConnect::_PAGE_404[] PROGMEM = {
"{{HEAD}}"
"<title>Page not found</title>"
"</head>"
"<body>"
"404 Not found"
"</body>"
"</html>"
};
And here we find "{{HEAD}}" and the closing tags of html and head.
And this goes on.
Now, from what I gather he made a HEAD using const char AutoConnect::_ELM_HTML_HEAD[] PROGMEM , that is actually the start of every HTML page.
Now what I don't understand is why is it named HEAD and not _ELM_HTML_HEAD like in the above declaration.
Also why and how exactly do you use it with {{}} (double curly braces).
I tried looking it up on google but I didn't didn't find an on-the-subject explanation.
Do you think you can help me understand ? Or at least point me towards some useful guide ?
Thank you !
The response to your question is probably here.
In you case, HEAD is a placeholder the value returned by
String AutoConnect::_token_HEAD(PageArgument& args) {
return String(_ELM_HTML_HEAD);
}
Look at:
PageElement page404(_PAGE_404, { { "HEAD", std::bind(&AutoConnect::_token_HEAD, this, std::placeholders::_1) } });
String html = page404.build();
Let's start with what the C++ compiler sees:
const char AutoConnect::_ELM_HTML_HEAD[] PROGMEM =
{
"just some (rather long) string literal"
"anything could stand here, the compiler does not care for..."
};
This applies for all members defined that way. Obviously, there are some HTML fragments stored in, but that's irrelevant from C++ point of view.
From C++ point of view, the {{ [...] }} fragments are just part of the string, too, and they don't have any meaning in HTML either. They certainly are insertion markers for some standard text pieces to produce the final HTML output – but that needs to be done by the final C++ executable, it is not part of neither C++ nor HTML. So you'll find some code somewhere that does something similar to the following:
char const* pattern = [...];
while(*pattern)
{
char const* start = strstr(pattern, "{{");
char const* end = strstr(start, "}}");
std::cout.write(pattern, start - pattern);
start += 2;
std::string_view key(start, end - start);
std::cout << fragments[key]; // assuming some map, mapping id to content
pattern = end + 2;
}
Be aware that this is incomplete!!! I do not care for not having found start and end markers (double braces) or for printing the rest of the string, if no replacement marker has been found any more; the real application would need to handle these cases appropriately.
The goal is to achieve a QDomDocument or something similar with the content of an HTML (not XML) document.
The problem is that some tags, especially script trigger errors:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var a = [1,2,3];
var b = (2<a.length);
</script>
</head>
<body/>
</html>
Not well formed: Element type "a.length" must be followed by either attribute specifications, ">" or "/>".
I understand that HTML is not the same as XML, but it seems reasonable that Qt has a solution for this:
Setting the parser to accept HTML
Another class for HTML
A way to set some tags name as CDATA.
My current try only achieves normal XML parsing:
QString mainHtml;
{
QFile file("main.html");
if (!file.open(QIODevice::ReadOnly)) qDebug() << "Error reading file main.html";
QTextStream stream(&file);
mainHtml = stream.readAll();
file.close();
}
QQDomDocument doc;
QString errStr;
int errLine=0, errCol=0;
doc.setContent( mainHtml, false, &errStr, &errLine, &errCol);
if (!errStr.isEmpty())
{
qDebug() << errStr << "L:" << errLine << ":" << errCol;
}
std::function<void(const QDomElement&, int)> printTags=
[&printTags](const QDomElement& elem, int tab)
{
QString space(3*tab, ' ');
QDomNode n = elem.firstChild();
for( ;!n.isNull(); n=n.nextSibling())
{
QDomElement e = n.toElement();
if(e.isNull()) continue;
qDebug() << space + e.tagName();
printTags( e, tab+1);
}
};
printTags(doc.documentElement(), 0);
Note: I would like to avoid including the full webkit for this.
I recommend to use htmlcxx. It is licensed under LPGL. It works on Linux and Windows. If you use windows compile with msys.
To compile it just extract the files and run
./configure --prefix=/usr/local/htmlcxx
make
make install
In your .pro file add the include and library directory.
INCLUDEPATH += /usr/local/htmlcxx/include
LIBS += -L/usr/local/htmlcxx/lib -lhtmlcxx
Usage example
#include <iostream>
#include "htmlcxx/html/ParserDom.h"
#include <stdlib.h>
int main (int argc, char *argv[])
{
using namespace std;
using namespace htmlcxx;
//Parse some html code
string html = "<html><body>heymyhome</body></html>";
HTML::ParserDom parser;
tree<HTML::Node> dom = parser.parseTree(html);
//Print whole DOM tree
cout << dom << endl;
//Dump all links in the tree
tree<HTML::Node>::iterator it = dom.begin();
tree<HTML::Node>::iterator end = dom.end();
for (; it != end; ++it)
{
if (strcasecmp(it->tagName().c_str(), "A") == 0)
{
it->parseAttributes();
cout << it->attribute("href").second << endl;
}
}
//Dump all text of the document
it = dom.begin();
end = dom.end();
for (; it != end; ++it)
{
if ((!it->isTag()) && (!it->isComment()))
{
cout << it->text() << " ";
}
}
cout << endl;
return 0;
}
Credits for the example:
https://github.com/bbxyard/sdk/blob/master/examples/htmlcxx/htmlcxx-demo.cpp
You can't use an XML parser for HTML. You either use htmlcxx or convert the HTML to valid XML. Then you are free to use QDomDocument, Qt XML parsers, etc.
QWebEngine has also parsing functionality, but brings a large overhead with the application.
I am new to the Grails platform and became interested in the TagLib component.
I have this application wherein I am to create a time select [24-hour format selection] made of two <select> tag: hour and time. So far I have coded my theory in this manner.
def timePicker = { attrs ->
out << "<g:select name='" + attrs['name'] + ".hour' from='${00..21}' />"
out << "<g:select name='" + attrs['name'] + ".minute' from='${00..59}' />"
}
However I can't display it in the page but it display the content of out in the webpage itself which is wrong. How can I have two <select> display properly on the .gsp by TagLib? Am i going to write it in the conventional <select> accompanied with <option> statements, or am going to utilize the g.select(attrs) syntax?
Thanks
you could use something like this:
def timePicker = { attrs ->
def hours = 0..21
def stringHours = hours.collect{ String.format('%02d', it) }
def minutes = 0..59
def stringMinutes = minutes.collect{ String.format('%02d', it) }
out << "${select(from: stringHours, name: attrs.name + '.hour')}"
out << "${select(from: stringMinutes, name: attrs.name + '.minute')}"
}
You can use a method call in GSP only:
def timePicker = { attrs ->
out << "${select(from: 00..21, name: attrs.name + '.hour')}"
out << "${select(from: 00..59, name: attrs.name + '.minute')}"
}
I have a column of WKT POLYGON values in MySQL (I inherited the db). The polys are queried and rendered on Google Maps. Since Google Maps polygon overlay requires an array of points, the previous user converted the WKT values to coordinate pairs and stored them in another column. This actually works rather well, but not well enough.
For one, the conversion was occasionally faulty, and for two, I am looking for ways to make this faster.
Re. the first issue, I have to re-implement this, and am looking for a converter that will convert a WKT poly into a string of coordinates. I am thinking I could use this to either write a stored procedure that will query the WKT column and spit out a string of JSON text that could be readily converted to Google Maps polys, or even preprocess all the WKT polys and store them as text like it is already done, but this time with correct values.
So, I am really looking for a function to convert WKT to a string of its constituent point coordinates, kinda like so
SELECT AsStringOfCoords(WKT_Column) FROM table WHERE condition
where AsStringOfCoords() would be my custom function.
I'd wrote a little C++ program to do MySQL WKT polygons to KML polygons.
This thing works as follows:
Read the information from the database
create a kml document
Rearrange the information and print it out to the file.
You can call the new kml to googlemaps and it shows pretty nice.
The source code is here...
#include <iostream>
#include <string>
/*
* Database includes...
*/
#include <mysql_connection.h>
#include <cppconn/driver.h>
#include <cppconn/exception.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>
#include <cppconn/prepared_statement.h>
#include "../iolib/IOCoreFuncs.h"
#include "../iolib/ioconfigurador.h"
using namespace std;
using namespace sql;
using namespace IOCore;
sql::Connection * conectaDB(string dbSvr, string dbUsr, string dbPwd, string dbNombre);
int main(int argc, char **argv) {
string qry, arproc;
Connection * dbCon;
Statement * stmt;
IOConfigurador * miConf;
ResultSet * rs;
//Cargar configuración...
if (argc == 3) {
arproc = argv[2];
} else {
cout << "Using mode: sqltokml <polygon id> <file kml to export>\n";
return 1;
}
dbCon = conectaDB("dbserver", "dbuser"), "dbpasswd", "dbname");
stmt = dbCon->createStatement();
qry = "SELECT name, astext(geoarea) from " + "table name" + " where id = '" + argv[1] + "';";
rs = stmt->executeQuery(qry);
if (rs->rowsCount() > 0) {
string polnombre, polcoords;
string salida;
while (rs->next()) {
ofstream sale;
polnombre = rs->getString(1);
polcoords = rs->getString(2);
salida = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\" xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n"
"<Document>\n"
"<name>" + polnombre + ".kml</name>\n"
"<Style id=\"sh_ylw-pushpin3\">\n"
"<IconStyle>\n"
"<scale>1.3</scale>\n"
"<Icon>\n"
"<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>\n"
"</Icon>\n"
"<hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\"/>\n"
"</IconStyle>\n"
"<LineStyle>\n"
"<color>467f5500</color>\n"
"<width>3</width>\n"
"</LineStyle>\n"
"<PolyStyle>\n"
"<color>46ff5555</color>\n"
"</PolyStyle>\n"
"</Style>\n"
"<StyleMap id=\"msn_ylw-pushpin10\">\n"
"<Pair>\n"
"<key>normal</key>\n"
"<styleUrl>#sn_ylw-pushpin30</styleUrl>\n"
"</Pair>\n"
"<Pair>\n"
"<key>highlight</key>\n"
"<styleUrl>#sh_ylw-pushpin3</styleUrl>\n"
"</Pair>\n"
"</StyleMap>\n"
"<Style id=\"sn_ylw-pushpin30\">\n"
"<IconStyle>\n"
"<scale>1.1</scale>\n"
"<Icon>\n"
"<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>\n"
"</Icon>\n"
"<hotSpot x=\"20\" y=\"2\" xunits=\"pixels\" yunits=\"pixels\"/>\n"
"</IconStyle>\n"
"<LineStyle>\n"
"<color>467f5500</color>\n"
"<width>3</width>\n"
"</LineStyle>\n"
"<PolyStyle>\n"
"<color>46ff5555</color>\n"
"</PolyStyle>\n"
"</Style>\n"
"<Folder>\n"
"<name>" + polnombre + "</name>\n"
"<Placemark>\n"
"<name>" + polnombre + "</name>\n"
"<styleUrl>#msn_ylw-pushpin10</styleUrl>\n"
"<Polygon>\n"
"<tessellate>1</tessellate>\n"
"<outerBoundaryIs>\n"
"<LinearRing>\n"
"<coordinates>\n";
//Coordinates tranformation...
polcoords = polcoords.substr(9, polcoords.size() - 11);
vector< string > lascoords = split(polcoords, ",");
for (unsigned i = 0; i < lascoords.size(); i++) {
salida += lascoords[i].substr(0, lascoords[i].find(" ")) + ",";
salida += lascoords[i].substr(lascoords[i].find(" ") + 1) + ",0 ";
}
salida += "\n</coordinates>\n"
"</LinearRing>\n"
"</outerBoundaryIs>\n"
"</Polygon>\n"
"</Placemark>\n"
"</Folder>\n"
"</Document>\n"
"</kml>";
sale.open(arproc.c_str(), ios::out | ios::app);
sale << salida ;
sale.close();
}
}
rs->close();
stmt->close();
dbCon->close();
}
sql::Connection * conectaDB(string dbSvr, string dbUsr, string dbPwd, string dbNombre)
{
sql::Connection * retval;
sql::Driver *ctrl;
try {
ctrl = get_driver_instance();
retval = ctrl->connect(dbSvr, dbUsr, dbPwd);
retval->setSchema(dbNombre);
} catch (sql::SQLException &err) {
cout<<"Errors... :( "<<err.what()<<"\ngoing out\n";
retval = 0;
}
return retval;
}
I hope this can help you. Is easy to translate this to MySQL stored proc, or use it inside PHP or another languages... I also have some php/javascript scripts to do the same things with points.