void WdgAddStation::OnSave() { QString Str = ui.leComment->text(); if(Str.capacity()<1) return; if(ui.sbFreq->value() > 100000 && ui.sbFreq->value() < 440000000) { emit Station(ui.leComment->text(), ui.sbFreq->value(), ui.comboBox->currentIndex()); close(); } }
QString KexiDB::escapeBLOB(const QByteArray& array, BLOBEscapingType type) { const int size = array.size(); if (size == 0) return QString(); int escaped_length = size * 2; if (type == BLOBEscape0xHex || type == BLOBEscapeOctal) escaped_length += 2/*0x or X'*/; else if (type == BLOBEscapeXHex) escaped_length += 3; //X' + ' QString str; str.reserve(escaped_length); if (str.capacity() < escaped_length) { KexiDBWarn << "KexiDB::Driver::escapeBLOB(): no enough memory (cannot allocate " << escaped_length << " chars)"; return QString(); } if (type == BLOBEscapeXHex) str = QString::fromLatin1("X'"); else if (type == BLOBEscape0xHex) str = QString::fromLatin1("0x"); else if (type == BLOBEscapeOctal) str = QString::fromLatin1("'"); int new_length = str.length(); //after X' or 0x, etc. if (type == BLOBEscapeOctal) { // only escape nonprintable characters as in Table 8-7: // http://www.postgresql.org/docs/8.1/interactive/datatype-binary.html // i.e. escape for bytes: < 32, >= 127, 39 ('), 92(\). for (int i = 0; i < size; i++) { const unsigned char val = array[i]; if (val < 32 || val >= 127 || val == 39 || val == 92) { str[new_length++] = '\\'; str[new_length++] = '\\'; str[new_length++] = '0' + val / 64; str[new_length++] = '0' + (val % 64) / 8; str[new_length++] = '0' + val % 8; } else { str[new_length++] = val; } } } else { for (int i = 0; i < size; i++) { const unsigned char val = array[i]; str[new_length++] = (val / 16) < 10 ? ('0' + (val / 16)) : ('A' + (val / 16) - 10); str[new_length++] = (val % 16) < 10 ? ('0' + (val % 16)) : ('A' + (val % 16) - 10); } } if (type == BLOBEscapeXHex || type == BLOBEscapeOctal) str[new_length++] = '\''; return str; }
void MainWindow::on_pushButton_4_clicked() { QTextDocument doc; QString txt; txt = ::textAt(h3,65,"ASAP Film Order") % ::textAt(h3,40,"From C&C Special Products Co. 952-881-0073") % ::textAt(h3,67,"Mark Robin") % ::textAt(h3,6,"Attn: Customer Service") % ::nbsp(63) % "Rip Settings:"% ::textAt(h3,103,"1) Film Positives") % ::textAt(h3,103,"2) DO NOT TRAP") % ::textAt(h3,103,"3) Send Pre Separated") % ::textAt(h3,6,"Date: " % ui->dateEdit->text()) % ::textAt(h3,6,"File Name: " % ui->lineEdit_2->text()); qDebug() << "The memory used is: " << txt.capacity(); doc.setHtml(txt); #if !defined(QT_NO_PRINTER) && !defined(QT_NO_PRINTDIALOG) QPrinter printer(QPrinter::HighResolution); QPrintDialog *dlg = new QPrintDialog(&printer, this); dlg->addEnabledOption(QAbstractPrintDialog::PrintSelection); dlg->setWindowTitle(tr("Print Document")); if (dlg->exec() == QDialog::Accepted) { QPrinter printer; // printer.setOutputFileName("c:\\temp\\filenew.pdf"); // printer.setOutputFormat(QPrinter::PdfFormat); qDebug() << "Sending to printer"; doc.print(&printer); printer.newPage(); printer.setOutputFileName("c:\\temp\\faxASAP.pdf"); printer.setOutputFormat(QPrinter::PdfFormat); qDebug() << "Creating PDF"; doc.print(&printer); printer.newPage(); } delete dlg; #endif }
bool QMakeParser::read(ProFile *pro, const QString &in, int line, SubGrammar grammar) { m_proFile = pro; m_lineNo = line; // Final precompiled token stream buffer QString tokBuff; // Worst-case size calculations: // - line marker adds 1 (2-nl) to 1st token of each line // - empty assignment "A=":2 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 0(1) + // TokValueTerminator(1) == 8 (9) // - non-empty assignment "A=B C":5 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokAssign(1) + 2(1) + // TokLiteral(1) + len(1) + "B"(1) + // TokLiteral(1) + len(1) + "C"(1) + TokValueTerminator(1) == 14 (15) // - variable expansion: "$$f":3 => // TokVariable(1) + hash(2) + len(1) + "f"(1) = 5 // - function expansion: "$$f()":5 => // TokFuncName(1) + hash(2) + len(1) + "f"(1) + TokFuncTerminator(1) = 6 // - scope: "X:":2 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokCondition(1) + // TokBranch(1) + len(2) + ... + len(2) + ... == 10 // - test: "X():":4 => // TokHashLiteral(1) + hash(2) + len(1) + "A"(1) + TokTestCall(1) + TokFuncTerminator(1) + // TokBranch(1) + len(2) + ... + len(2) + ... == 11 // - "for(A,B):":9 => // TokForLoop(1) + hash(2) + len(1) + "A"(1) + // len(2) + TokLiteral(1) + len(1) + "B"(1) + TokValueTerminator(1) + // len(2) + ... + TokTerminator(1) == 14 (15) tokBuff.reserve((in.size() + 1) * 5); ushort *tokPtr = (ushort *)tokBuff.constData(); // Current writing position // Expression precompiler buffer. QString xprBuff; xprBuff.reserve(tokBuff.capacity()); // Excessive, but simple ushort *buf = (ushort *)xprBuff.constData(); // Parser state m_blockstack.clear(); m_blockstack.resize(1); QStack<ParseCtx> xprStack; xprStack.reserve(10); // We rely on QStrings being null-terminated, so don't maintain a global end pointer. const ushort *cur = (const ushort *)in.unicode(); m_canElse = false; freshLine: m_state = StNew; m_invert = false; m_operator = NoOperator; m_markLine = m_lineNo; m_inError = false; int parens = 0; // Braces in value context int argc = 0; int wordCount = 0; // Number of words in currently accumulated expression int lastIndent = 0; // Previous line's indentation, to detect accidental continuation abuse bool lineMarked = true; // For in-expression markers ushort needSep = TokNewStr; // Met unquoted whitespace ushort quote = 0; ushort term = 0; Context context; ushort *ptr; if (grammar == ValueGrammar) { context = CtxPureValue; ptr = tokPtr + 2; } else { context = CtxTest; ptr = buf + 4; } ushort *xprPtr = ptr; #define FLUSH_LHS_LITERAL() \ do { \ if ((tlen = ptr - xprPtr)) { \ finalizeHashStr(xprPtr, tlen); \ if (needSep) { \ wordCount++; \ needSep = 0; \ } \ } else { \ ptr -= 4; \ } \ } while (0) #define FLUSH_RHS_LITERAL() \ do { \ if ((tlen = ptr - xprPtr)) { \ xprPtr[-2] = TokLiteral | needSep; \ xprPtr[-1] = tlen; \ if (needSep) { \ wordCount++; \ needSep = 0; \ } \ } else { \ ptr -= 2; \ } \ } while (0) #define FLUSH_LITERAL() \ do { \ if (context == CtxTest) \ FLUSH_LHS_LITERAL(); \ else \ FLUSH_RHS_LITERAL(); \ } while (0) #define FLUSH_VALUE_LIST() \ do { \ if (wordCount > 1) { \ xprPtr = tokPtr; \ if (*xprPtr == TokLine) \ xprPtr += 2; \ tokPtr[-1] = ((*xprPtr & TokMask) == TokLiteral) ? wordCount : 0; \ } else { \ tokPtr[-1] = 0; \ } \ tokPtr = ptr; \ putTok(tokPtr, TokValueTerminator); \ } while (0) const ushort *end; // End of this line const ushort *cptr; // Start of next line bool lineCont; int indent; if (context == CtxPureValue) { end = (const ushort *)in.unicode() + in.length(); cptr = 0; lineCont = false; indent = 0; // just gcc being stupid goto nextChr; } forever { ushort c; // First, skip leading whitespace for (indent = 0; ; ++cur, ++indent) { c = *cur; if (c == '\n') { ++cur; goto flushLine; } else if (!c) { cur = 0; goto flushLine; } else if (c != ' ' && c != '\t' && c != '\r') { break; } } // Then strip comments. Yep - no escaping is possible. for (cptr = cur;; ++cptr) { c = *cptr; if (c == '#') { for (end = cptr; (c = *++cptr);) { if (c == '\n') { ++cptr; break; } } if (end == cur) { // Line with only a comment (sans whitespace) if (m_markLine == m_lineNo) m_markLine++; // Qmake bizarreness: such lines do not affect line continuations goto ignore; } break; } if (!c) { end = cptr; break; } if (c == '\n') { end = cptr++; break; } } // Then look for line continuations. Yep - no escaping here as well. forever { // We don't have to check for underrun here, as we already determined // that the line is non-empty. ushort ec = *(end - 1); if (ec == '\\') { --end; lineCont = true; break; } if (ec != ' ' && ec != '\t' && ec != '\r') { lineCont = false; break; } --end; } // Finally, do the tokenization ushort tok, rtok; int tlen; newWord: do { if (cur == end) goto lineEnd; c = *cur++; } while (c == ' ' || c == '\t'); forever { if (c == '$') { if (*cur == '$') { // may be EOF, EOL, WS, '#' or '\\' if past end cur++; FLUSH_LITERAL(); if (!lineMarked) { lineMarked = true; *ptr++ = TokLine; *ptr++ = (ushort)m_lineNo; } term = 0; tok = TokVariable; c = *cur; if (c == '[') { ptr += 4; tok = TokProperty; term = ']'; c = *++cur; } else if (c == '{') { ptr += 4; term = '}'; c = *++cur; } else if (c == '(') { ptr += 2; tok = TokEnvVar; term = ')'; c = *++cur; } else { ptr += 4; } xprPtr = ptr; rtok = tok; while ((c & 0xFF00) || c == '.' || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '/' && term)) { *ptr++ = c; if (++cur == end) { c = 0; goto notfunc; } c = *cur; } if (tok == TokVariable && c == '(') tok = TokFuncName; notfunc: if (ptr == xprPtr) languageWarning(fL1S("Missing name in expansion")); if (quote) tok |= TokQuoted; if (needSep) { tok |= needSep; wordCount++; } tlen = ptr - xprPtr; if (rtok != TokVariable || !resolveVariable(xprPtr, tlen, needSep, &ptr, &buf, &xprBuff, &tokPtr, &tokBuff, cur, in)) { if (rtok == TokVariable || rtok == TokProperty) { xprPtr[-4] = tok; uint hash = ProString::hash((const QChar *)xprPtr, tlen); xprPtr[-3] = (ushort)hash; xprPtr[-2] = (ushort)(hash >> 16); xprPtr[-1] = tlen; } else { xprPtr[-2] = tok; xprPtr[-1] = tlen; } } if ((tok & TokMask) == TokFuncName) { cur++; funcCall: { xprStack.resize(xprStack.size() + 1); ParseCtx &top = xprStack.top(); top.parens = parens; top.quote = quote; top.terminator = term; top.context = context; top.argc = argc; top.wordCount = wordCount; } parens = 0; quote = 0; term = 0; argc = 1; context = CtxArgs; nextToken: wordCount = 0; nextWord: ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; needSep = TokNewStr; goto newWord; } if (term) { checkTerm: if (c != term) { parseError(fL1S("Missing %1 terminator [found %2]") .arg(QChar(term)) .arg(c ? QString(c) : QString::fromLatin1("end-of-line"))); pro->setOk(false); m_inError = true; // Just parse on, as if there was a terminator ... } else { cur++; } } joinToken: ptr += (context == CtxTest) ? 4 : 2; xprPtr = ptr; needSep = 0; goto nextChr; } } else if (c == '\\') {
bool KexiCSVExport::exportData(KexiDB::TableOrQuerySchema& tableOrQuery, const Options& options, int rowCount, QTextStream *predefinedTextStream) { KexiDB::Connection* conn = tableOrQuery.connection(); if (!conn) return false; if (rowCount == -1) rowCount = KexiDB::rowCount(tableOrQuery); if (rowCount == -1) return false; //! @todo move this to non-GUI location so it can be also used via command line //! @todo add a "finish" page with a progressbar. //! @todo look at rowCount whether the data is really large; //! if so: avoid copying to clipboard (or ask user) because of system memory //! @todo OPTIMIZATION: use fieldsExpanded(true /*UNIQUE*/) //! @todo OPTIMIZATION? (avoid multiple data retrieving) look for already fetched data within KexiProject.. KexiDB::QuerySchema* query = tableOrQuery.query(); if (!query) query = tableOrQuery.table()->query(); KexiDB::QueryColumnInfo::Vector fields( query->fieldsExpanded( KexiDB::QuerySchema::WithInternalFields ) ); QString buffer; KSaveFile *kSaveFile = 0; QTextStream *stream = 0; const bool copyToClipboard = options.mode==Clipboard; if (copyToClipboard) { //! @todo (during exporting): enlarge bufSize by factor of 2 when it became too small uint bufSize = QMIN((rowCount<0 ? 10 : rowCount) * fields.count() * 20, 128000); buffer.reserve( bufSize ); if (buffer.capacity() < bufSize) { kdWarning() << "KexiCSVExportWizard::exportData() cannot allocate memory for " << bufSize << " characters" << endl; return false; } } else { if (predefinedTextStream) { stream = predefinedTextStream; } else { if (options.fileName.isEmpty()) {//sanity kdWarning() << "KexiCSVExportWizard::exportData(): fname is empty" << endl; return false; } kSaveFile = new KSaveFile(options.fileName); if (0 == kSaveFile->status()) stream = kSaveFile->textStream(); if (0 != kSaveFile->status() || !stream) {//sanity kdWarning() << "KexiCSVExportWizard::exportData(): status != 0 or stream == 0" << endl; delete kSaveFile; return false; } } } //! @todo escape strings #define _ERR \ delete [] isText; \ if (kSaveFile) { kSaveFile->abort(); delete kSaveFile; } \ return false #define APPEND(what) \ if (copyToClipboard) buffer.append(what); else (*stream) << (what) // line endings should be as in RFC 4180 #define CSV_EOLN "\r\n" // 0. Cache information const uint fieldsCount = query->fieldsExpanded().count(); //real fields count without internals const QCString delimiter( options.delimiter.left(1).latin1() ); const bool hasTextQuote = !options.textQuote.isEmpty(); const QString textQuote( options.textQuote.left(1) ); const QCString escapedTextQuote( (textQuote + textQuote).latin1() ); //ok? //cache for faster checks bool *isText = new bool[fieldsCount]; bool *isDateTime = new bool[fieldsCount]; bool *isTime = new bool[fieldsCount]; bool *isBLOB = new bool[fieldsCount]; uint *visibleFieldIndex = new uint[fieldsCount]; // bool isInteger[fieldsCount]; //cache for faster checks // bool isFloatingPoint[fieldsCount]; //cache for faster checks for (uint i=0; i<fieldsCount; i++) { KexiDB::QueryColumnInfo* ci; const int indexForVisibleLookupValue = fields[i]->indexForVisibleLookupValue(); if (-1 != indexForVisibleLookupValue) { ci = query->expandedOrInternalField( indexForVisibleLookupValue ); visibleFieldIndex[i] = indexForVisibleLookupValue; } else { ci = fields[i]; visibleFieldIndex[i] = i; } isText[i] = ci->field->isTextType(); isDateTime[i] = ci->field->type()==KexiDB::Field::DateTime; isTime[i] = ci->field->type()==KexiDB::Field::Time; isBLOB[i] = ci->field->type()==KexiDB::Field::BLOB; // isInteger[i] = fields[i]->field->isIntegerType() // || fields[i]->field->type()==KexiDB::Field::Boolean; // isFloatingPoint[i] = fields[i]->field->isFPNumericType(); } // 1. Output column names if (options.addColumnNames) { for (uint i=0; i<fieldsCount; i++) { if (i>0) APPEND( delimiter ); if (hasTextQuote){ APPEND( textQuote + fields[i]->captionOrAliasOrName().replace(textQuote, escapedTextQuote) + textQuote ); } else { APPEND( fields[i]->captionOrAliasOrName() ); } } APPEND(CSV_EOLN); } KexiGUIMessageHandler handler; KexiDB::Cursor *cursor = conn->executeQuery(*query); if (!cursor) { handler.showErrorMessage(conn); _ERR; } for (cursor->moveFirst(); !cursor->eof() && !cursor->error(); cursor->moveNext()) { const uint realFieldCount = QMIN(cursor->fieldCount(), fieldsCount); for (uint i=0; i<realFieldCount; i++) { const uint real_i = visibleFieldIndex[i]; if (i>0) APPEND( delimiter ); if (cursor->value(real_i).isNull()) continue; if (isText[real_i]) { if (hasTextQuote) APPEND( textQuote + QString(cursor->value(real_i).toString()).replace(textQuote, escapedTextQuote) + textQuote ); else APPEND( cursor->value(real_i).toString() ); } else if (isDateTime[real_i]) { //avoid "T" in ISO DateTime APPEND( cursor->value(real_i).toDateTime().date().toString(Qt::ISODate)+" " + cursor->value(real_i).toDateTime().time().toString(Qt::ISODate) ); } else if (isTime[real_i]) { //time is temporarily stored as null date + time... APPEND( cursor->value(real_i).toTime().toString(Qt::ISODate) ); } else if (isBLOB[real_i]) { //BLOB is escaped in a special way if (hasTextQuote) //! @todo add options to suppport other types from KexiDB::BLOBEscapingType enum... APPEND( textQuote + KexiDB::escapeBLOB(cursor->value(real_i).toByteArray(), KexiDB::BLOBEscapeHex) + textQuote ); else APPEND( KexiDB::escapeBLOB(cursor->value(real_i).toByteArray(), KexiDB::BLOBEscapeHex) ); } else {//other types APPEND( cursor->value(real_i).toString() ); } } APPEND(CSV_EOLN); } if (copyToClipboard) buffer.squeeze(); if (!conn->deleteCursor(cursor)) { handler.showErrorMessage(conn); _ERR; } if (copyToClipboard) kapp->clipboard()->setText(buffer, QClipboard::Clipboard); delete [] isText; delete [] isDateTime; delete [] isTime; delete [] isBLOB; delete [] visibleFieldIndex; if (kSaveFile) { if (!kSaveFile->close()) { kdWarning() << "KexiCSVExportWizard::exportData(): error close(); status == " << kSaveFile->status() << endl; } delete kSaveFile; } return true; }
bool KexiCSVExport::exportData(KDbTableOrQuerySchema *tableOrQuery, const Options& options, int recordCount, QTextStream *predefinedTextStream) { KDbConnection* conn = tableOrQuery->connection(); if (!conn) return false; KDbQuerySchema* query = tableOrQuery->query(); QList<QVariant> queryParams; if (!query) { query = tableOrQuery->table()->query(); } else { queryParams = KexiMainWindowIface::global()->currentParametersForQuery(query->id()); } if (recordCount == -1) recordCount = KDb::recordCount(tableOrQuery, queryParams); if (recordCount == -1) return false; //! @todo move this to non-GUI location so it can be also used via command line //! @todo add a "finish" page with a progressbar. //! @todo look at recordCount whether the data is really large; //! if so: avoid copying to clipboard (or ask user) because of system memory //! @todo OPTIMIZATION: use fieldsExpanded(true /*UNIQUE*/) //! @todo OPTIMIZATION? (avoid multiple data retrieving) look for already fetched data within KexiProject.. KDbQueryColumnInfo::Vector fields(query->fieldsExpanded(KDbQuerySchema::WithInternalFields)); QString buffer; QScopedPointer<QSaveFile> kSaveFile; QTextStream *stream = 0; QScopedPointer<QTextStream> kSaveFileTextStream; const bool copyToClipboard = options.mode == Clipboard; if (copyToClipboard) { //! @todo (during exporting): enlarge bufSize by factor of 2 when it became too small int bufSize = qMin((recordCount < 0 ? 10 : recordCount) * fields.count() * 20, 128000); buffer.reserve(bufSize); if (buffer.capacity() < bufSize) { qWarning() << "Cannot allocate memory for " << bufSize << " characters"; return false; } } else { if (predefinedTextStream) { stream = predefinedTextStream; } else { if (options.fileName.isEmpty()) {//sanity qWarning() << "Fname is empty"; return false; } kSaveFile.reset(new QSaveFile(options.fileName)); qDebug() << "QSaveFile Filename:" << kSaveFile->fileName(); if (kSaveFile->open(QIODevice::WriteOnly)) { kSaveFileTextStream.reset(new QTextStream(kSaveFile.data())); stream = kSaveFileTextStream.data(); qDebug() << "have a stream"; } if (QFileDevice::NoError != kSaveFile->error() || !stream) {//sanity qWarning() << "Status != 0 or stream == 0"; //! @todo show error return false; } } } //! @todo escape strings #define _ERR \ if (kSaveFile) { kSaveFile->cancelWriting(); } \ return false #define APPEND(what) \ if (copyToClipboard) buffer.append(what); else (*stream) << (what) // use native line ending for copying, RFC 4180 one for saving to file #define APPEND_EOLN \ if (copyToClipboard) { APPEND('\n'); } else { APPEND("\r\n"); } qDebug() << 0 << "Columns: " << query->fieldsExpanded().count(); // 0. Cache information const int fieldsCount = query->fieldsExpanded().count(); //real fields count without internals const QByteArray delimiter(options.delimiter.left(1).toLatin1()); const bool hasTextQuote = !options.textQuote.isEmpty(); const QString textQuote(options.textQuote.left(1)); const QByteArray escapedTextQuote((textQuote + textQuote).toLatin1()); //ok? //cache for faster checks QScopedArrayPointer<bool> isText(new bool[fieldsCount]); QScopedArrayPointer<bool> isDateTime(new bool[fieldsCount]); QScopedArrayPointer<bool> isTime(new bool[fieldsCount]); QScopedArrayPointer<bool> isBLOB(new bool[fieldsCount]); QScopedArrayPointer<int> visibleFieldIndex(new int[fieldsCount]); // bool isInteger[fieldsCount]; //cache for faster checks // bool isFloatingPoint[fieldsCount]; //cache for faster checks for (int i = 0; i < fieldsCount; i++) { KDbQueryColumnInfo* ci; const int indexForVisibleLookupValue = fields[i]->indexForVisibleLookupValue(); if (-1 != indexForVisibleLookupValue) { ci = query->expandedOrInternalField(indexForVisibleLookupValue); visibleFieldIndex[i] = indexForVisibleLookupValue; } else { ci = fields[i]; visibleFieldIndex[i] = i; } const KDbField::Type t = ci->field->type(); // cache: evaluating type of expressions can be expensive isText[i] = KDbField::isTextType(t); isDateTime[i] = t == KDbField::DateTime; isTime[i] = t == KDbField::Time; isBLOB[i] = t == KDbField::BLOB; // isInteger[i] = KDbField::isIntegerType(t) // || t == KDbField::Boolean; // isFloatingPoint[i] = KDbField::isFPNumericType(t); } // 1. Output column names if (options.addColumnNames) { for (int i = 0; i < fieldsCount; i++) { //qDebug() << "Adding column names"; if (i > 0) { APPEND(delimiter); } if (hasTextQuote) { APPEND(textQuote + fields[i]->captionOrAliasOrName().replace(textQuote, escapedTextQuote) + textQuote); } else { APPEND(fields[i]->captionOrAliasOrName()); } } APPEND_EOLN } KexiGUIMessageHandler handler; KDbCursor *cursor = conn->executeQuery(query, queryParams); if (!cursor) { handler.showErrorMessage(conn->result()); _ERR; } for (cursor->moveFirst(); !cursor->eof() && !cursor->result().isError(); cursor->moveNext()) { //qDebug() << "Adding records"; const int realFieldCount = qMin(cursor->fieldCount(), fieldsCount); for (int i = 0; i < realFieldCount; i++) { const int real_i = visibleFieldIndex[i]; if (i > 0) { APPEND(delimiter); } if (cursor->value(real_i).isNull()) { continue; } if (isText[real_i]) { if (hasTextQuote) APPEND(textQuote + QString(cursor->value(real_i).toString()).replace(textQuote, escapedTextQuote) + textQuote); else APPEND(cursor->value(real_i).toString()); } else if (isDateTime[real_i]) { //avoid "T" in ISO DateTime APPEND(cursor->value(real_i).toDateTime().date().toString(Qt::ISODate) + " " + cursor->value(real_i).toDateTime().time().toString(Qt::ISODate)); } else if (isTime[real_i]) { //time is temporarily stored as null date + time... APPEND(cursor->value(real_i).toTime().toString(Qt::ISODate)); } else if (isBLOB[real_i]) { //BLOB is escaped in a special way if (hasTextQuote) //! @todo add options to suppport other types from KDbBLOBEscapingType enum... APPEND(textQuote + KDb::escapeBLOB(cursor->value(real_i).toByteArray(), KDb::BLOBEscapeHex) + textQuote); else APPEND(KDb::escapeBLOB(cursor->value(real_i).toByteArray(), KDb::BLOBEscapeHex)); } else {//other types APPEND(cursor->value(real_i).toString()); } } APPEND_EOLN } if (copyToClipboard) buffer.squeeze(); if (!conn->deleteCursor(cursor)) { handler.showErrorMessage(conn->result()); _ERR; } if (copyToClipboard) QApplication::clipboard()->setText(buffer, QClipboard::Clipboard); qDebug() << "Done"; if (kSaveFile) { stream->flush(); if (!kSaveFile->commit()) { qWarning() << "Error commiting the file" << kSaveFile->fileName(); } } return true; }