20#include "kexicsvexport.h"
21#include "kexicsvwidgets.h"
22#include <main/startup/KexiStartupFileDialog.h>
23#include <kexidb/cursor.h>
24#include <kexidb/utils.h>
25#include <core/keximainwindow.h>
26#include <core/kexiproject.h>
27#include <core/kexipartinfo.h>
28#include <core/kexipartmanager.h>
29#include <core/kexiguimsghandler.h>
30#include <kexiutils/utils.h>
31#include <widget/kexicharencodingcombobox.h>
33#include <tqcheckbox.h>
34#include <tqgroupbox.h>
35#include <tqclipboard.h>
36#include <tdeapplication.h>
38#include <kiconloader.h>
39#include <kactivelabel.h>
40#include <kpushbutton.h>
41#include <tdeapplication.h>
46using namespace KexiCSVExport;
49 : mode(File), itemId(0), addColumnNames(true)
55 mode = (args[
"destinationType"]==
"file")
56 ? KexiCSVExport::File : KexiCSVExport::Clipboard;
58 if (args.contains(
"delimiter"))
59 delimiter = args[
"delimiter"];
61 delimiter = (mode==File) ? KEXICSV_DEFAULT_FILE_DELIMITER : KEXICSV_DEFAULT_CLIPBOARD_DELIMITER;
63 if (args.contains(
"textQuote"))
64 textQuote = args[
"textQuote"];
66 textQuote = (mode==File) ? KEXICSV_DEFAULT_FILE_TEXT_QUOTE : KEXICSV_DEFAULT_CLIPBOARD_TEXT_QUOTE;
69 itemId = args[
"itemId"].toInt(&ok);
72 if (args.contains(
"forceDelimiter"))
74 if (args.contains(
"addColumnNames"))
75 addColumnNames = (args[
"addColumnNames"]==
"1");
82 const Options& options,
int rowCount, TQTextStream *predefinedTextStream)
108 KSaveFile *kSaveFile = 0;
109 TQTextStream *stream = 0;
111 const bool copyToClipboard = options.mode==Clipboard;
112 if (copyToClipboard) {
114 uint bufSize = TQMIN((rowCount<0 ? 10 : rowCount) * fields.count() * 20, 128000);
115 buffer.reserve( bufSize );
116 if (buffer.capacity() < bufSize) {
117 kdWarning() <<
"KexiCSVExportWizard::exportData() cannot allocate memory for " << bufSize
118 <<
" characters" << endl;
123 if (predefinedTextStream) {
124 stream = predefinedTextStream;
127 if (options.fileName.isEmpty()) {
128 kdWarning() <<
"KexiCSVExportWizard::exportData(): fname is empty" << endl;
131 kSaveFile =
new KSaveFile(options.fileName);
132 if (0 == kSaveFile->status())
133 stream = kSaveFile->textStream();
134 if (0 != kSaveFile->status() || !stream) {
135 kdWarning() <<
"KexiCSVExportWizard::exportData(): status != 0 or stream == 0" << endl;
146 if (kSaveFile) { kSaveFile->abort(); delete kSaveFile; } \
149#define APPEND(what) \
150 if (copyToClipboard) buffer.append(what); else (*stream) << (what)
153#define CSV_EOLN "\r\n"
157 const TQCString delimiter( options.delimiter.left(1).latin1() );
158 const bool hasTextQuote = !options.textQuote.isEmpty();
159 const TQString textQuote( options.textQuote.left(1) );
160 const TQCString escapedTextQuote( (textQuote + textQuote).latin1() );
162 bool *isText =
new bool[fieldsCount];
163 bool *isDateTime =
new bool[fieldsCount];
164 bool *isTime =
new bool[fieldsCount];
165 bool *isBLOB =
new bool[fieldsCount];
166 uint *visibleFieldIndex =
new uint[fieldsCount];
169 for (uint i=0; i<fieldsCount; i++) {
170 KexiDB::QueryColumnInfo* ci;
171 const int indexForVisibleLookupValue = fields[i]->indexForVisibleLookupValue();
172 if (-1 != indexForVisibleLookupValue) {
174 visibleFieldIndex[i] = indexForVisibleLookupValue;
178 visibleFieldIndex[i] = i;
182 isDateTime[i] = ci->field->
type()==KexiDB::Field::DateTime;
183 isTime[i] = ci->field->
type()==KexiDB::Field::Time;
191 if (options.addColumnNames) {
192 for (uint i=0; i<fieldsCount; i++) {
196 APPEND( textQuote + fields[i]->captionOrAliasOrName().replace(textQuote, escapedTextQuote) + textQuote );
199 APPEND( fields[i]->captionOrAliasOrName() );
205 KexiGUIMessageHandler handler;
208 handler.showErrorMessage(conn);
212 const uint realFieldCount = TQMIN(cursor->
fieldCount(), fieldsCount);
213 for (uint i=0; i<realFieldCount; i++) {
214 const uint real_i = visibleFieldIndex[i];
217 if (cursor->
value(real_i).isNull())
219 if (isText[real_i]) {
221 APPEND( textQuote + TQString(cursor->
value(real_i).toString()).replace(textQuote, escapedTextQuote) + textQuote );
223 APPEND( cursor->
value(real_i).toString() );
225 else if (isDateTime[real_i]) {
226 APPEND( cursor->
value(real_i).toDateTime().date().toString(TQt::ISODate)+
" "
227 + cursor->
value(real_i).toDateTime().time().toString(TQt::ISODate) );
229 else if (isTime[real_i]) {
230 APPEND( cursor->
value(real_i).toTime().toString(TQt::ISODate) );
232 else if (isBLOB[real_i]) {
240 APPEND( cursor->
value(real_i).toString() );
250 handler.showErrorMessage(conn);
255 kapp->clipboard()->setText(buffer, TQClipboard::Clipboard);
258 delete [] isDateTime;
261 delete [] visibleFieldIndex;
264 if (!kSaveFile->close()) {
265 kdWarning() <<
"KexiCSVExportWizard::exportData(): error close(); status == "
266 << kSaveFile->status() << endl;
Options used in KexiCSVExportWizard contructor.
bool assign(TQMap< TQString, TQString > &args)
Assigns args.
int itemId
Table or query ID.
TQString forceDelimiter
Used for "clipboard" mode.
Provides database connection, allowing queries and data modification.
bool deleteCursor(Cursor *cursor)
Cursor * executeQuery(const TQString &statement, uint cursor_options=0)
virtual TQVariant value(uint i)=0
KexiDB::QuerySchema provides information about database query.
@ WithInternalFields
Like Default but internal fields (for lookup) are appended.
QueryColumnInfo::Vector fieldsExpanded(FieldsExpandedOptions options=Default)
QueryColumnInfo * expandedOrInternalField(uint index)
QuerySchema * query() const
TableSchema * table() const
Connection * connection() const
int rowCount(Connection &conn, const TQString &sql)
KEXI_DB_EXPORT TQString escapeBLOB(const TQByteArray &array, BLOBEscapingType type)
@ BLOBEscapeHex
escaping like 1FAD without quotes or prefixes