File indexing completed on 2025-01-19 13:27:13

0001 /* This file is part of the KDE project
0002    Copyright (C) 1999 David Faure <faure@kde.org>
0003    Copyright (C) 2004 Nicolas GOUTTE <goutte@kde.org>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "csvexportdialog.h"
0022 #include "csvexport.h"
0023 
0024 #include "sheets/Map.h"
0025 #include "sheets/Sheet.h"
0026 
0027 #include <kcharsets.h>
0028 #include <kmessagebox.h>
0029 #include <KSharedConfig>
0030 
0031 #include <QGuiApplication>
0032 #include <QTextCodec>
0033 #include <QValidator>
0034 #include <QDebug>
0035 
0036 using namespace Calligra::Sheets;
0037 
0038 CSVExportDialog::CSVExportDialog(QWidget * parent)
0039         : KoDialog(parent),
0040         m_dialog(new ExportDialogUI(this)),
0041         m_delimiter(","),
0042         m_textquote('"')
0043 {
0044     setButtons(KoDialog::Ok | KoDialog::Cancel);
0045     setDefaultButton(KoDialog::Ok);
0046     QGuiApplication::restoreOverrideCursor();
0047 
0048     QStringList encodings;
0049     encodings << i18nc("Descriptive encoding name", "Recommended ( %1 )" , "UTF-8");
0050     encodings << i18nc("Descriptive encoding name", "Locale ( %1 )" , QString(QTextCodec::codecForLocale()->name()));
0051     encodings += KCharsets::charsets()->descriptiveEncodingNames();
0052     // Add a few non-standard encodings, which might be useful for text files
0053     const QString description(i18nc("Descriptive encoding name", "Other ( %1 )"));
0054     encodings << description.arg("Apple Roman"); // Apple
0055     encodings << description.arg("IBM 850") << description.arg("IBM 866"); // MS DOS
0056     encodings << description.arg("CP 1258"); // Windows
0057 
0058     m_dialog->comboBoxEncoding->addItems(encodings);
0059 
0060     setMainWidget(m_dialog);
0061 
0062     // Invalid 'Other' delimiters
0063     // - Quotes
0064     // - CR,LF,Vertical-tab,Formfeed,ASCII bel
0065     QRegExp rx("^[^\"'\r\n\v\f\a]{0,1}$");
0066     m_delimiterValidator = new QRegExpValidator(rx, m_dialog->m_delimiterBox);
0067     m_dialog->m_delimiterEdit->setValidator(m_delimiterValidator);
0068 
0069     connect(m_dialog->m_delimiterBox, SIGNAL(clicked(int)),
0070             this, SLOT(delimiterClicked(int)));
0071     connect(m_dialog->m_delimiterEdit, SIGNAL(returnPressed()),
0072             this, SLOT(returnPressed()));
0073     connect(m_dialog->m_delimiterEdit, SIGNAL(textChanged(QString)),
0074             this, SLOT(textChanged(QString)));
0075     connect(m_dialog->m_comboQuote, SIGNAL(activated(QString)),
0076             this, SLOT(textquoteSelected(QString)));
0077     connect(m_dialog->m_selectionOnly, SIGNAL(toggled(bool)),
0078             this, SLOT(selectionOnlyChanged(bool)));
0079     connect(this, SIGNAL(okClicked()), SLOT(slotOk()));
0080     connect(this, SIGNAL(cancelClicked()), this, SLOT(slotCancel()));
0081 
0082     loadSettings();
0083 }
0084 
0085 CSVExportDialog::~CSVExportDialog()
0086 {
0087     saveSettings();
0088     QGuiApplication::setOverrideCursor(Qt::WaitCursor);
0089     delete m_delimiterValidator;
0090 }
0091 
0092 void CSVExportDialog::loadSettings()
0093 {
0094     KConfigGroup configGroup = KSharedConfig::openConfig()->group("CSVDialog Settings");
0095     m_textquote = configGroup.readEntry("textQuote", "\"")[0];
0096     m_delimiter = configGroup.readEntry("delimiter", ",");
0097     const QString codecText = configGroup.readEntry("codec", "");
0098     bool selectionOnly = configGroup.readEntry("selectionOnly", false);
0099     const QString sheetDelim = configGroup.readEntry("sheetDelimiter", m_dialog->m_sheetDelimiter->text());
0100     bool delimAbove = configGroup.readEntry("sheetDelimiterAbove", false);
0101     const QString eol = configGroup.readEntry("eol", "\r\n");
0102 
0103     // update widgets
0104     if (!codecText.isEmpty()) {
0105         m_dialog->comboBoxEncoding->setCurrentIndex(m_dialog->comboBoxEncoding->findText(codecText));
0106     }
0107     if (m_delimiter == ",")
0108         m_dialog->m_radioComma->setChecked(true);
0109     else if (m_delimiter == "\t")
0110         m_dialog->m_radioTab->setChecked(true);
0111     else if (m_delimiter == " ")
0112         m_dialog->m_radioSpace->setChecked(true);
0113     else if (m_delimiter == ";")
0114         m_dialog->m_radioSemicolon->setChecked(true);
0115     else {
0116         m_dialog->m_radioOther->setChecked(true);
0117         m_dialog->m_delimiterEdit->setText(m_delimiter);
0118     }
0119     m_dialog->m_comboQuote->setCurrentIndex(m_textquote == '\'' ? 1 : m_textquote == '"' ? 0 : 2);
0120     m_dialog->m_selectionOnly->setChecked(selectionOnly);
0121     m_dialog->m_sheetDelimiter->setText(sheetDelim);
0122     m_dialog->m_delimiterAboveAll->setChecked(delimAbove);
0123     if (eol == "\r\n")
0124         m_dialog->radioEndOfLineCRLF->setChecked(true);
0125     else if (eol == "\r")
0126         m_dialog->radioEndOfLineCR->setChecked(true);
0127     else
0128         m_dialog->radioEndOfLineLF->setChecked(true);
0129 }
0130 
0131 void CSVExportDialog::saveSettings()
0132 {
0133     KConfigGroup configGroup = KSharedConfig::openConfig()->group("CSVDialog Settings");
0134     configGroup.writeEntry("textQuote", QString(m_textquote));
0135     configGroup.writeEntry("delimiter", m_delimiter);
0136     configGroup.writeEntry("codec", m_dialog->comboBoxEncoding->currentText());
0137     configGroup.writeEntry("selectionOnly", exportSelectionOnly());
0138     configGroup.writeEntry("sheetDelimiter", getSheetDelimiter());
0139     configGroup.writeEntry("sheetDelimiterAbove", printAlwaysSheetDelimiter());
0140     configGroup.writeEntry("eol", getEndOfLine());
0141     configGroup.sync();
0142 }
0143 
0144 void CSVExportDialog::fillSheet(Map * map)
0145 {
0146     m_dialog->m_sheetList->clear();
0147     QListWidgetItem *item;
0148 
0149     foreach(Sheet* sheet, map->sheetList()) {
0150         item = new QListWidgetItem(sheet->sheetName() ,m_dialog->m_sheetList);
0151         item->setCheckState(Qt::Checked);
0152         m_dialog->m_sheetList->addItem(item);
0153     }
0154 }
0155 
0156 QChar CSVExportDialog::getDelimiter() const
0157 {
0158     return m_delimiter[0];
0159 }
0160 
0161 QChar CSVExportDialog::getTextQuote() const
0162 {
0163     return m_textquote;
0164 }
0165 
0166 bool CSVExportDialog::printAlwaysSheetDelimiter() const
0167 {
0168     return m_dialog->m_delimiterAboveAll->isChecked();
0169 }
0170 
0171 QString CSVExportDialog::getSheetDelimiter() const
0172 {
0173     return m_dialog->m_sheetDelimiter->text();
0174 }
0175 
0176 bool CSVExportDialog::exportSheet(QString const & sheetName) const
0177 {
0178     for (int i = 0; i < m_dialog->m_sheetList->count(); ++i) {
0179         QListWidgetItem *const item = m_dialog->m_sheetList->item(i);
0180         if (item->checkState() == Qt::Checked) {
0181             if (item->text() == sheetName) {
0182                 return true;
0183             }
0184         }
0185     }
0186     return false;
0187 }
0188 
0189 void CSVExportDialog::slotOk()
0190 {
0191     accept();
0192 }
0193 
0194 void CSVExportDialog::slotCancel()
0195 {
0196     reject();
0197 }
0198 
0199 void CSVExportDialog::returnPressed()
0200 {
0201     if (!m_dialog->m_radioOther->isChecked())
0202         return;
0203 
0204     m_delimiter = m_dialog->m_delimiterEdit->text();
0205 }
0206 
0207 void CSVExportDialog::textChanged(const QString &)
0208 {
0209 
0210     if (m_dialog->m_delimiterEdit->text().isEmpty()) {
0211         enableButtonOk(! m_dialog->m_radioOther->isChecked());
0212         return;
0213     }
0214 
0215     m_dialog->m_radioOther->setChecked(true);
0216     delimiterClicked(4);
0217 }
0218 
0219 void CSVExportDialog::delimiterClicked(int id)
0220 {
0221     enableButtonOk(true);
0222 
0223     //Erase "Other Delimiter" text box if the user has selected one of
0224     //the standard options instead (comma, semicolon, tab or space)
0225     if (id != 4)
0226         m_dialog->m_delimiterEdit->setText("");
0227 
0228     switch (id) {
0229     case 0: // comma
0230         m_delimiter = ",";
0231         break;
0232     case 1: // semicolon
0233         m_delimiter = ";";
0234         break;
0235     case 2: // tab
0236         m_delimiter = "\t";
0237         break;
0238     case 3: // space
0239         m_delimiter = " ";
0240         break;
0241     case 4: // other
0242         enableButtonOk(! m_dialog->m_delimiterEdit->text().isEmpty());
0243         m_delimiter = m_dialog->m_delimiterEdit->text();
0244         break;
0245     }
0246 }
0247 
0248 void CSVExportDialog::textquoteSelected(const QString & mark)
0249 {
0250     m_textquote = mark[0];
0251 }
0252 
0253 void CSVExportDialog::selectionOnlyChanged(bool on)
0254 {
0255     m_dialog->m_sheetList->setEnabled(!on);
0256     m_dialog->m_delimiterLineBox->setEnabled(!on);
0257 
0258     if (on)
0259         m_dialog->m_tabWidget->setCurrentIndex(1);
0260 }
0261 
0262 bool CSVExportDialog::exportSelectionOnly() const
0263 {
0264     return m_dialog->m_selectionOnly->isChecked();
0265 }
0266 
0267 QTextCodec* CSVExportDialog::getCodec(void) const
0268 {
0269     const QString strCodec(KCharsets::charsets()->encodingForName(m_dialog->comboBoxEncoding->currentText()));
0270     qDebug(lcCsvExport) << "Encoding:" << strCodec;
0271 
0272     bool ok = false;
0273     QTextCodec* codec = QTextCodec::codecForName(strCodec.toUtf8());
0274 
0275     // If QTextCodec has not found a valid encoding, so try with KCharsets.
0276     if (codec) {
0277         ok = true;
0278     } else {
0279         codec = KCharsets::charsets()->codecForName(strCodec, ok);
0280     }
0281 
0282     // Still nothing?
0283     if (!codec || !ok) {
0284         // Default: UTF-8
0285         qWarning(lcCsvExport) << "Cannot find encoding:" << strCodec;
0286         // ### TODO: what parent to use?
0287         KMessageBox::error(0, i18n("Cannot find encoding: %1", strCodec));
0288         return 0;
0289     }
0290 
0291     return codec;
0292 }
0293 
0294 QString CSVExportDialog::getEndOfLine(void) const
0295 {
0296     QString strReturn;
0297     if (m_dialog->radioEndOfLineLF->isChecked())
0298         strReturn = "\n";
0299     else if (m_dialog->radioEndOfLineCRLF->isChecked())
0300         strReturn = "\r\n";
0301     else if (m_dialog->radioEndOfLineCR->isChecked())
0302         strReturn = "\r";
0303     else
0304         strReturn = "\n";
0305 
0306     return strReturn;
0307 }