table margin in qprint and QTextDocument using html as input - html

im trying to print an invoice in a4 format using qprint and QTextDocument with html ..but i couldn't find any solution to adjust the margin-left and margin-right of the html table...

my example
QString data;
m_printer.setPageSize(QPrinter::A4);
m_printer.setOrientation(QPrinter::Landscape);
QTextStream out(&m_strStream);
const int rowCount = m_TableWidget->model()->rowCount();
const int columnCount = m_TableWidget->model()->columnCount();
out << "<html>\n"
"<head>\n"
"<meta Content=\"Text/html; charset=Windows-1251\">\n"
<< QString("<title>%1</title>\n").arg("title")
<< "</head>\n"
"<body bgcolor=#ffffff link=#5000A0>\n"
"<table border=1 cellspacing=0 cellpadding=2>\n";
out << "<thead><tr bgcolor=#f0f0f0>";
for (int column = 0; column < columnCount; column++)
if (!m_TableWidget->isColumnHidden(column))
out << QString("<th>%1</th>").arg(m_TableWidget->model()->headerData(column, Qt::Horizontal).toString());
out << "</tr></thead>\n";
// data table
out << "<tr>";
for (int column = 0; column < columnCount; column++) {
if(column%7 == 1) {
QString data = m_TableWidget->model()->data(m_TableWidget->model()->index(0, column)).toString().simplified();
out << QString("<td colspan=7>%1</td>").arg((!data.isEmpty()) ? data : QString(" "));
} else if(column == 0){
QString data = m_TableWidget->model()->data(m_TableWidget->model()->index(0, column)).toString().simplified();
out << QString("<td bkcolor=0>%1</td>").arg((!data.isEmpty()) ? data : QString(" "));
}
}
out << "</tr>\n";
for (int row = 1; row < rowCount; row++) {
out << "<tr>";
for (int column = 0; column < columnCount; column++) {
if(row==1 && column==1)
{ data =m_ComboBox->currentText().simplified();
}
if (!m_TableWidget->isColumnHidden(column)) {
data = m_TableWidget->model()->data(m_TableWidget->model()->index(row, column)).toString().simplified();
out << QString("<td bkcolor=0>%1</td>").arg((!data.isEmpty()) ? data : QString(" "));
}
}
out << "</tr>\n";
}
out << "</table>\n"
"</body>\n"
"</html>\n";
m_document = new QTextDocument();
m_document->setHtml(m_strStream);
m_dialog = new QPrintDialog(&m_printer, NULL);
if (m_dialog->exec() == QDialog::Accepted) {
m_document->print(&m_printer);
}
delete m_document;

Related

Refer to json individual objects in cpp crow

i am using a cpp crow library and i am having difficulty in accessing individual objects i am attaching my code here.
CROW_ROUTE(app,"/hello/<string>")
([](string name){
crow::json::wvalue x;
x["name"] = "llllds";
x["Town"] = "Texas";
x["nickname"] = "drax";
x["father"] = "Nethan";
if (name == "Nothing")
cout << "Bad Responce";
std::ostringstream os;
cout << name << " is the required query";
val = x[name];
return val;
And i want to return my name can anyone help me with this. Thanks in advance
I used JSON for Modern C++ within crow (https://github.com/nlohmann/json)
Here is an example CROW_ROUTE I wrote
CROW_ROUTE(app, "/palindromes/<string>/<string>")([](const request &req, response &res, string ID, string words){
palindromeHash.insert({ID, words}); //ignore this
nlohmann::json x;
x = getPalindromes(palindromeHash.at(ID));
palindromeHash.erase(ID); //ignore this
res.sendJSON(x);
});
//getPalindromesFunction()
nlohmann::json getPalindromes(string data){
nlohmann::json x;
unordered_map<string, bool> hashmap;
string word = "";
std::string::size_type i = data.find("%20");
while (i != std::string::npos){
data.erase(i, 3);
data.insert(i, " ");
i = data.find("%20", i);
}
for(int i = 0; i < data.size(); i++){
if(data[i] == ' '){
hashmap.insert({word, true});
word = "";
}
else{
word += data[i];
}
}
string temp;
vector<string> words;
int numValid = 0;
for(auto& i: hashmap){
temp = i.first;
reverse(temp.begin(), temp.end());
auto got = hashmap.find(temp);
if(got != hashmap.end()){
words.push_back(i.first);
numValid++;
}
}
x["words"] = words;
x["numValid"] = numValid;
return x;
}
As you can see it returns a JSON object x that holds palindromes. The sendJSON() function is something I added to crow_all.h. Add it under the struct response section on line 7215
void sendJSON(const nlohmann::json& data){
std::string response = data.dump();
add_header("Access-Control-Allow-Origin", "*");
add_header("Content-Type", "text/html");
write(response);
end();
}
Remember to include "json.h" in both main.cpp and crow_all.h. The res.sendJSON will send it to my JS file which can loop through the JSON with ease.
$.get("/palindromes/" + ID + "/" + curr_line, {}, function(response){
let x = JSON.parse(response); //This will allow JS to read the C++ JSON
for(let i = 0; i < x.words.length; i++){
term.write(x.words[i] + "\r\n");
}
}

simple HTML validator

I have a homework problem which asks me to write a simple HTML validator which checks for matching start and end tags.
Here is my code and input file below.
void removeSpaces(std::string &str){
int count = 0;
for (int i = 0; str[i]; i++)
if (str[i] != ' ')
str[count++] = str[i];
str[count] = '\0';
}
bool isHtmlMatched(std::vector<std::string>& htmlTags){
std::stack<std::string> temp;
typedef std::vector<std::string>::const_iterator Iter;
for (int i = 0; i < htmlTags.size(); i++){
if (htmlTags[i][1] != '/')
temp.push(htmlTags[i]);
else{
if (temp.empty()) return false;
std::string open = temp.top().substr(1);
std::string close = htmlTags[i].substr(2);
std::cout << open << " " << close <<std::endl;
if (open != close){
std::cout << "Failed at where " << temp.top() << " didnt match with " << htmlTags[i] << std::endl;
return false;
}
else{
temp.pop();
}
}
}
if(temp.empty()){
return true;
}
else{
std::cout << " These start tags ";
while(!temp.empty()){
std::cout << temp.top() << " ";
temp.pop();
}
std::cout << "do not have a matching end tag " <<std::endl;
return false;
}
}
int main() {
std::vector<std::string> htmlTags;
std::string input_line;
std::ifstream file("Validhtml.txt");
std::string tag;
int line = 0;
while(std::getline(file, input_line)){
int pointer = 0;
int position_start = input_line.find("<",pointer);
while (position_start != std::string::npos){
if(input_line.find(">", position_start + 1) == std::string::npos){
std::cout << "INVALID HTML" << std::endl;
std::cout << "ERROR ON LINE " << line + 1 << std::endl;
return 0;
}
int position_end = input_line.find(">", position_start + 1);
tag = input_line.substr(position_start, position_end - position_start + 1);
removeSpaces(tag);
htmlTags.push_back(tag);
pointer = position_end + 1;
position_start = input_line.find("<", pointer);
}
line++;
}
for(int i = 0; i < htmlTags.size(); i++){
std::cout << htmlTags[i] << std::endl;
}
if(!isHtmlMatched(htmlTags)){
std::cout << "INVALID HTML" << std::endl;
}
else{
std::cout << "VALID HTML" << std::endl;
}
return 0;
}
Input file:
<html><
head></head><body> My HTML page
<p></p> <h2>Hello world! </ h2>
<ol><li> #myfiles</li>
</ol>
</body >
</html>
I currently have two problem with this code.
I don't know how to read tags that are split in different lines, for example the <head> tag at the end of the first and start of the second line of the input file.
Even after I removed all the white space, this program still won't recognize <h2> and </ h2> are a matching tag. Same issue goes for <body> and </body >
Hope someone can help me with this.
I worked on this for a bit and got something I think should work for you.
Here's how the code works: First, we open the html file and push it all into a string with no whitespace. Next, we send that string to a function to detect tags. Once a tag is detected, we try to see if its an opening or closing tag. We then save the tag to the correct container (either the opening_tags container or the closing_tags container). Finally, we run a series of tests on the two containers we have. (1) Are they the same size? (2) Are they empty (meaning no tags were detected)? (3) Do all tags in the opening_tags container correspond to a tag in the closing_tags container.
If all three of our tests are passed, then we can say the html file is valid (based on tag matching).
For the containers, I used hashsets (known as std::unordered_set in C++). This is because hashsets are really fast in inserting and removing elements. In your specific instance, the order of the tags shouldn't matter. However, keep in mind that, in an actual validator, it would matter greatly.
If you have any more questions on my code, feel free to ask! Without any more waiting, here's the code:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <unordered_set>
// Gets rid of all file white space and returns the string
std::string condense(std::ifstream&);
// Tests if all tags are matching and returns if they are
// (true) or if they aren't (false)
bool validate(const std::string&);
int main()
{
std::ifstream html_stream("input.html");
const std::string html_string = condense(html_stream);
const bool html_valid = validate(html_string);
// Prints the html string (mostly for debugging)
std::cout << html_string << '\n' << std::endl;
if (html_valid)
std::cout << "Valid HTML!" << std::endl;
else
std::cout << "Invalid HTML..." << std::endl;
}
std::string condense(std::ifstream& stream)
{
std::string file_no_whitespace;
if (stream.is_open())
{
std::string cur_token;
while (stream >> cur_token)
file_no_whitespace += cur_token;
}
else
std::cerr << "File is not open!" << std::endl;
return file_no_whitespace;
}
bool validate(const std::string& data)
{
// These should be the same size if the html is valid
// (based only on tag matching)
std::unordered_set<std::string> opening_tags, closing_tags;
// For tags like '<br />'
std::unordered_set<std::string> self_closing_tags;
// Keeps track of the current tag to push into either
// opening_tags or closing_tags
bool tagging_open;
// Process each character to make tags
for (size_t i = 0; i < data.size(); ++i)
{
const auto* cur_char = &data.at(i);
if (*cur_char == '<')
{
std::string cur_tag;
if (*(cur_char + 1) == '/')
{ // Test for closing tag
tagging_open = false;
i++;
cur_char++;
}
else // Tag is an opening tag
tagging_open = true;
i++;
cur_char++;
while (*cur_char != '>') // Until tag closes
{
cur_tag += *cur_char;
i++;
cur_char++;
}
// Test for self-closing tag
if (*(cur_char - 1) == '/')
self_closing_tags.insert(cur_tag);
// Not self-closing, so it's a normal type of tag
else if (tagging_open)
opening_tags.insert(cur_tag);
else if (!tagging_open)
closing_tags.insert(cur_tag);
}
}
// If the hashsets aren't the same size, then we automatically know
// there is at least one unmatched tag
if (opening_tags.size() != closing_tags.size())
return false;
// If the hashsets are both empty, then we know there are no tags
if (opening_tags.empty())
return false;
// If both above tests have been passed, we now need to make sure that
// every opening tag has a matching closing tag
std::vector<bool> tag_match(opening_tags.size(), false);
size_t tag_match_pos = 0;
for (const auto& tag : opening_tags)
{
auto closing_tag_itr = closing_tags.find(tag);
if (closing_tag_itr != std::end(closing_tags))
{
tag_match.at(tag_match_pos) = true;
tag_match_pos++;
// Remove match tag to avoid duplicates causing false-positives
closing_tags.erase(closing_tag_itr);
}
}
bool all_matched = true;
for (const auto& match : tag_match)
{ // Make sure all values in the 'tag_match' vector are true
if (!match)
{
all_matched = false;
break;
}
}
return all_matched;
}

Gzip string unable to concatenate to a string

I'm a newbie in c++ and I've been trying to search for an answer to this question but can hardly found an answer I'm trying to compress an html string body with zlib in gzip compression the compression gets done successfully but when I try to concatenate it to another string it won't concatenate at all rendering the body to be blank here is the compression code:
void compress_message(){
z_stream zs;
char outbuffer[32768];
long strlen = content.size();
int ret;
string outstring;
memset(&zs, 0, sizeof(zs));
if (deflateInit2(&zs,
Z_BEST_COMPRESSION,
Z_DEFLATED,
MOD_GZIP_ZLIB_WINDOWSIZE + 16,
MOD_GZIP_ZLIB_CFACTOR,
Z_DEFAULT_STRATEGY) != Z_OK
) {
throw(std::runtime_error("deflateInit2 failed while compressing."));
}
content = "";
zs.next_in = (Bytef*) content.data();
zs.avail_in = strlen;
do {
//cout << "compressing..." << endl;
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
zs.avail_out = sizeof(outbuffer);
ret = deflate(&zs, Z_FINISH);
if (content.size() < zs.total_out) {
// append the block to the output string
content.append(outbuffer,
zs.total_out - content.size());
}
} while (ret == Z_OK);
deflateEnd(&zs);
//cout << "original: " << content << endl;
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
ostringstream oss;
oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
throw(std::runtime_error(oss.str()));
}
}
base64 conversion function:
string tobase64(string data) {
string code64,
output = "";
int i = 0,
j = 0;
unsigned int slen = data.size();
const char* bytes_to_encode;
code64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
unsigned char char_array_3[3],
char_array_4[4];
bytes_to_encode = data.c_str();
while(slen--){
char_array_3[i++] = bytes_to_encode[j++];
if(3 == i){
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; i < 4; i++){
output += code64[char_array_4[i]];
}
i = 0;
}
}
if (i)
{
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = ( char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
for (j = 0; (j < i + 1); j++)
output += code64[char_array_4[j]];
while((i++ < 3))
output += '=';
}
return output;
}
the string is successfully compressed but when I concatenate it to the string response like:
string final_content = ("HTTP/1.1 200 OK\r\n"+headers+"\r\n\r\n");
content = tobase64(content);
final_content += content;
I also tried
final_content.append(content);
They both have the same result the body is never concatenated the final_content when printed only shows:
HTTP/1.1 200 OK
...
Content-type: text/html
and the compressed string is never included have been trying to find answers online and couldn't figure it out please help. I'm working this on ubuntu 18.04

Get total rows filtered by if() statement in google apps scripts

I've got this fn().
Is there any simple way to return the number of filtered rows by this conditional statement in Google app scripts?
function getGlobers(globers, project){
var body = "";
var data = globers.getValues();
for( i = 0; i < data.length; i++ ){
if( data[i][2] == project ){
body += "<tr><td style=" + STYLE.TD + ">" + data[i].join("</td><td style=" + STYLE.TD + ">") + "</td></tr>";
}
}
return body;
}
Thanks.
for example (see comments in code)
function getGlobers(globers, project){
var body = "";
var n = 0; // use a variable to count
var data = globers.getValues();
for( i = 0; i < data.length; i++ ){
if( data[i][2] == project ){
n++;// increment each time condition is true
body += "<tr><td style=" + STYLE.TD + ">" + data[i].join("</td><td style=" + STYLE.TD + ">") + "</td></tr>";
}
}
return [body,n];// return an array of 2 values
}
Usage :
var result = getGlobers(range,project);
Logger.log('array result = '+result);
Logger.log('body (string) = '+result[0]);
Logger.log('length (integer) = '+result[1]);
note : instead of an array you could also return an object with 2 properties... a matter of choice.
EDIT : an example using object properties :
function getGlobers(globers, project){
var body = "";
var n = 0;
var result = {};
var data = globers.getValues();
for( i = 0; i < data.length; i++ ){
if( data[i][2] == project ){
n++;
body += "<tr><td style=" + STYLE.TD + ">" + data[i].join("</td><td style=" + STYLE.TD + ">") + "</td></tr>";
}
}
result['body'] = body;
result['length'] = n;
return result;
}
Usage :
var result = getGlobers(range,project);
Logger.log('body = '+result.body);
Logger.log('length = '+result.length);

Alternative version of find_if which finds all, not just the first?

Is there an alternative version of std::find_if that returns an iterator over all found elements, instead of just the first one?
Example:
bool IsOdd (int i) {
return ((i % 2) == 1);
}
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
std::vector<int>::iterator it = find_if(v.begin(), v.end(), IsOdd);
for(; it != v.end(); ++it) {
std::cout << "odd: " << *it << std::endl;
}
You can just use a for loop:
for (std::vector<int>:iterator it = std::find_if(v.begin(), v.end(), IsOdd);
it != v.end();
it = std::find_if(++it, v.end(), IsOdd))
{
// ...
}
Alternatively, you can put your condition and action into a functor (performing the action only if the condition is true) and just use std::foreach.
in STL there isn't, but boost offers this funcionality:
boost::algorithm::find_all
First always try to come up with typical STL usage itself, you can go for boost as well. Here is more simplified form from the above mentioned answer by Charles.
vec_loc = find_if(v3.begin(), v3.end(), isOdd);
if (vec_loc != v3.end())
{
cout << "odd elem. found at " << (vec_loc - v3.begin()) << "and elem found is " << *vec_loc << endl;
++vec_loc;
}
for (;vec_loc != v3.end();vec_loc++)
{
vec_loc = find_if(vec_loc, v3.end(), isOdd);
if (vec_loc == v3.end())
break;
cout << "odd elem. found at " << (vec_loc - v3.begin()) << "and elem found is " << *vec_loc << endl;
}