File indexing completed on 2022-09-27 16:29:26

0001 /**
0002  * SPDX-FileCopyrightText: (C) 2003 Sébastien Laoût <slaout@linux62.org>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "softwareimporters.h"
0008 
0009 #include <QDialogButtonBox>
0010 #include <QFileDialog>
0011 #include <QGroupBox>
0012 #include <QHBoxLayout>
0013 #include <QLocale>
0014 #include <QPushButton>
0015 #include <QRadioButton>
0016 #include <QRegExp>
0017 #include <QStandardPaths>
0018 #include <QVBoxLayout>
0019 #include <QtCore/QDir>
0020 #include <QtCore/QStack>
0021 #include <QtCore/QString>
0022 #include <QtCore/QTextStream>
0023 #include <QtXml/QDomDocument>
0024 
0025 #include <KConfigGroup>
0026 #include <KLocalizedString>
0027 #include <KMessageBox>
0028 #include <KTextEdit>
0029 
0030 #include "basketfactory.h"
0031 #include "basketscene.h"
0032 #include "bnpview.h"
0033 #include "debugwindow.h"
0034 #include "global.h"
0035 #include "icon_names.h"
0036 #include "notefactory.h"
0037 #include "tools.h"
0038 #include "xmlwork.h"
0039 
0040 /** class TreeImportDialog: */
0041 
0042 TreeImportDialog::TreeImportDialog(QWidget *parent)
0043     : QDialog(parent)
0044 {
0045     QWidget *page = new QWidget(this);
0046     QVBoxLayout *topLayout = new QVBoxLayout(page);
0047 
0048     // QDialog options
0049     setWindowTitle(i18n("Import Hierarchy"));
0050 
0051     QWidget *mainWidget = new QWidget(this);
0052     QVBoxLayout *mainLayout = new QVBoxLayout;
0053     setLayout(mainLayout);
0054     mainLayout->addWidget(mainWidget);
0055 
0056     setObjectName("ImportHeirachy");
0057     setModal(true);
0058 
0059     m_choices = new QGroupBox(i18n("How to Import the Notes?"), page);
0060     m_choiceLayout = new QVBoxLayout();
0061     m_choices->setLayout(m_choiceLayout);
0062 
0063     m_hierarchy_choice = new QRadioButton(i18n("&Keep original hierarchy (all notes in separate baskets)"), m_choices);
0064     m_separate_baskets_choice = new QRadioButton(i18n("&First level notes in separate baskets"), m_choices);
0065     m_one_basket_choice = new QRadioButton(i18n("&All notes in one basket"), m_choices);
0066 
0067     m_hierarchy_choice->setChecked(true);
0068     m_choiceLayout->addWidget(m_hierarchy_choice);
0069     m_choiceLayout->addWidget(m_separate_baskets_choice);
0070     m_choiceLayout->addWidget(m_one_basket_choice);
0071 
0072     topLayout->addWidget(m_choices);
0073     topLayout->addStretch(10);
0074 
0075     mainLayout->addWidget(page);
0076 
0077     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0078     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0079     okButton->setDefault(true);
0080     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0081     connect(buttonBox, &QDialogButtonBox::accepted, this, &TreeImportDialog::accept);
0082     connect(buttonBox, &QDialogButtonBox::rejected, this, &TreeImportDialog::reject);
0083     mainLayout->addWidget(buttonBox);
0084 }
0085 
0086 TreeImportDialog::~TreeImportDialog()
0087 {
0088 }
0089 
0090 int TreeImportDialog::choice()
0091 {
0092     if (m_hierarchy_choice->isChecked())
0093         return 1;
0094     else if (m_separate_baskets_choice->isChecked())
0095         return 2;
0096     else
0097         return 3;
0098 }
0099 
0100 /** class TextFileImportDialog: */
0101 
0102 TextFileImportDialog::TextFileImportDialog(QWidget *parent)
0103     : QDialog(parent)
0104 {
0105     QWidget *page = new QWidget(this);
0106     QVBoxLayout *topLayout = new QVBoxLayout(page);
0107     QVBoxLayout *mainLayout = new QVBoxLayout;
0108     setLayout(mainLayout);
0109 
0110     // QDialog options
0111     setWindowTitle(i18n("Import Text File"));
0112     setObjectName("ImportTextFile");
0113     setModal(true);
0114 
0115     m_choices = new QGroupBox(i18n("Format of the Text File"), page);
0116     mainLayout->addWidget(m_choices);
0117     m_choiceLayout = new QVBoxLayout;
0118     m_choices->setLayout(m_choiceLayout);
0119 
0120     m_emptyline_choice = new QRadioButton(i18n("Notes separated by an &empty line"), m_choices);
0121     m_newline_choice = new QRadioButton(i18n("One &note per line"), m_choices);
0122     m_dash_choice = new QRadioButton(i18n("Notes begin with a &dash (-)"), m_choices);
0123     m_star_choice = new QRadioButton(i18n("Notes begin with a &star (*)"), m_choices);
0124     m_anotherSeparator = new QRadioButton(i18n("&Use another separator:"), m_choices);
0125 
0126     m_choiceLayout->addWidget(m_emptyline_choice);
0127     m_choiceLayout->addWidget(m_newline_choice);
0128     m_choiceLayout->addWidget(m_dash_choice);
0129     m_choiceLayout->addWidget(m_star_choice);
0130     m_choiceLayout->addWidget(m_anotherSeparator);
0131 
0132     QWidget *indentedTextEdit = new QWidget(m_choices);
0133     m_choiceLayout->addWidget(indentedTextEdit);
0134 
0135     QHBoxLayout *hLayout = new QHBoxLayout(indentedTextEdit);
0136     hLayout->addSpacing(20);
0137     m_customSeparator = new KTextEdit(indentedTextEdit);
0138     hLayout->addWidget(m_customSeparator);
0139 
0140     m_all_in_one_choice = new QRadioButton(i18n("&All in one note"), m_choices);
0141     m_choiceLayout->addWidget(m_all_in_one_choice);
0142 
0143     m_emptyline_choice->setChecked(true);
0144     topLayout->addWidget(m_choices);
0145 
0146     connect(m_customSeparator, &KTextEdit::textChanged, this, &TextFileImportDialog::customSeparatorChanged);
0147 
0148     mainLayout->addWidget(page);
0149 
0150     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0151     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0152     okButton->setDefault(true);
0153     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0154     connect(buttonBox, &QDialogButtonBox::accepted, this, &TextFileImportDialog::accept);
0155     connect(buttonBox, &QDialogButtonBox::rejected, this, &TextFileImportDialog::reject);
0156     mainLayout->addWidget(buttonBox);
0157 }
0158 
0159 TextFileImportDialog::~TextFileImportDialog()
0160 {
0161 }
0162 
0163 QString TextFileImportDialog::separator()
0164 {
0165     if (m_emptyline_choice->isChecked())
0166         return "\n\n";
0167     else if (m_newline_choice->isChecked())
0168         return "\n";
0169     else if (m_dash_choice->isChecked())
0170         return "\n-";
0171     else if (m_star_choice->isChecked())
0172         return "\n*";
0173     else if (m_anotherSeparator->isChecked())
0174         return m_customSeparator->toPlainText();
0175     else if (m_all_in_one_choice->isChecked())
0176         return QString();
0177     else
0178         return "\n\n";
0179 }
0180 
0181 void TextFileImportDialog::customSeparatorChanged()
0182 {
0183     if (!m_anotherSeparator->isChecked())
0184         m_anotherSeparator->toggle();
0185 }
0186 
0187 /** namespace SoftwareImporters: */
0188 
0189 void SoftwareImporters::finishImport(BasketScene *basket)
0190 {
0191     // Unselect the last inserted group:
0192     basket->unselectAll();
0193 
0194     // Focus the FIRST note (the last inserted note is currently focused!):
0195     basket->setFocusedNote(basket->firstNoteShownInStack());
0196 
0197     // Relayout every notes at their new place and simulate a load animation (because already loaded just after the creation).
0198     // Without a relayouting, notes on the bottom would comes from the top (because they were inserted on top) and clutter the animation load:
0199     basket->relayoutNotes();
0200     basket->save();
0201 }
0202 
0203 void SoftwareImporters::importTextFile()
0204 {
0205     QString fileName = QFileDialog::getOpenFileName(nullptr, QString(), "kfiledialog:///:ImportTextFile", "*|All files");
0206     if (fileName.isEmpty())
0207         return;
0208 
0209     TextFileImportDialog dialog;
0210     if (dialog.exec() == QDialog::Rejected)
0211         return;
0212     QString separator = dialog.separator();
0213 
0214     QFile file(fileName);
0215     if (file.open(QIODevice::ReadOnly)) {
0216         QTextStream stream(&file);
0217         QString content = stream.readAll();
0218         QStringList list = (separator.isEmpty() ? QStringList(content) : content.split(separator));
0219 
0220         // First create a basket for it:
0221         QString title = i18nc("From TextFile.txt", "From %1", QUrl::fromLocalFile(fileName).fileName());
0222         BasketFactory::newBasket(QStringLiteral("txt"), title);
0223         BasketScene *basket = Global::bnpView->currentBasket();
0224         basket->load();
0225 
0226         // Import every notes:
0227         for (QStringList::Iterator it = list.begin(); it != list.end(); ++it) {
0228             Note *note = NoteFactory::createNoteFromText((*it).trimmed(), basket);
0229             basket->insertNote(note, basket->firstNote(), Note::BottomColumn);
0230         }
0231 
0232         // Finish the export:
0233         finishImport(basket);
0234     }
0235 }
0236