File indexing completed on 2022-11-29 20:24:10

0001 // -*- indent-tabs-mode:nil -*-
0002 // vim: set ts=4 sts=4 sw=4 et:
0003 /* This file is part of the KDE project
0004    Copyright (C) 2000 David Faure <faure@kde.org>
0005    Copyright (C) 2002-2003 Alexander Kellett <lypanov@kde.org>
0006 
0007    This program is free software; you can redistribute it and/or
0008    modify it under the terms of the GNU General Public
0009    License version 2 or at your option version 3 as published by
0010    the Free Software Foundation.
0011 
0012    This program is distributed in the hope that it will be useful,
0013    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015    General Public License for more details.
0016 
0017    You should have received a copy of the GNU General Public License
0018    along with this program; see the file COPYING.  If not, write to
0019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020    Boston, MA 02110-1301, USA.
0021 */
0022 
0023 #include "importers.h"
0024 #include "globalbookmarkmanager.h"
0025 
0026 #include "kbookmarkmodel/model.h"
0027 #include "toplevel.h" // for KEBApp
0028 
0029 #include "keditbookmarks_debug.h"
0030 #include <QFileDialog>
0031 
0032 #include <KMessageBox>
0033 
0034 #include <KBookmark>
0035 #include <KBookmarkManager>
0036 
0037 #include <kbookmarkimporter.h>
0038 #include <kbookmarkimporter_ie.h>
0039 #include <kbookmarkimporter_opera.h>
0040 //#include <kbookmarkimporter_crash.h>
0041 #include <KBookmarkDomBuilder>
0042 #include <QStandardPaths>
0043 #include <kbookmarkimporter_ns.h>
0044 #include <kwidgetsaddons_version.h>
0045 
0046 ImportCommand::ImportCommand(KBookmarkModel *model)
0047     : QUndoCommand()
0048     , m_model(model)
0049     , m_utf8(false)
0050     , m_folder(false)
0051     , m_cleanUpCmd(nullptr)
0052 {
0053 }
0054 
0055 void ImportCommand::setVisibleName(const QString &visibleName)
0056 {
0057     m_visibleName = visibleName;
0058     setText(i18nc("(qtundo-format)", "Import %1 Bookmarks", visibleName));
0059 }
0060 
0061 QString ImportCommand::folder() const
0062 {
0063     return m_folder ? i18n("%1 Bookmarks", visibleName()) : QString();
0064 }
0065 
0066 ImportCommand *ImportCommand::importerFactory(KBookmarkModel *model, const QString &type)
0067 {
0068     if (type == QLatin1String("Galeon"))
0069         return new GaleonImportCommand(model);
0070     else if (type == QLatin1String("IE"))
0071         return new IEImportCommand(model);
0072     else if (type == QLatin1String("KDE2"))
0073         return new KDE2ImportCommand(model);
0074     else if (type == QLatin1String("Opera"))
0075         return new OperaImportCommand(model);
0076     // else if (type == "Crashes") return new CrashesImportCommand();
0077     else if (type == QLatin1String("Moz"))
0078         return new MozImportCommand(model);
0079     else if (type == QLatin1String("NS"))
0080         return new NSImportCommand(model);
0081     else {
0082         qCCritical(KEDITBOOKMARKS_LOG) << "ImportCommand::importerFactory() - invalid type (" << type << ")!";
0083         return nullptr;
0084     }
0085 }
0086 
0087 ImportCommand *ImportCommand::performImport(KBookmarkModel *model, const QString &type, QWidget *top)
0088 {
0089     ImportCommand *importer = ImportCommand::importerFactory(model, type);
0090 
0091     Q_ASSERT(importer);
0092 
0093     QString mydirname = importer->requestFilename();
0094     if (mydirname.isEmpty()) {
0095         delete importer;
0096         return nullptr;
0097     }
0098 
0099 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
0100     int answer = KMessageBox::questionTwoActionsCancel(top,
0101 #else
0102     int answer = KMessageBox::questionYesNoCancel(top,
0103 #endif
0104                                                        i18n("Import as a new subfolder or replace all the current bookmarks?"),
0105                                                        i18nc("@title:window", "%1 Import", importer->visibleName()),
0106                                                        KGuiItem(i18n("As New Folder")),
0107                                                        KGuiItem(i18n("Replace")));
0108 
0109     if (answer == KMessageBox::Cancel) {
0110         delete importer;
0111         return nullptr;
0112     }
0113 
0114 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
0115     importer->import(mydirname, answer == KMessageBox::ButtonCode::PrimaryAction);
0116 #else
0117     importer->import(mydirname, answer == KMessageBox::Yes);
0118 #endif
0119     return importer;
0120 }
0121 
0122 void ImportCommand::doCreateHoldingFolder(KBookmarkGroup &bkGroup)
0123 {
0124     bkGroup = GlobalBookmarkManager::self()->mgr()->root().createNewFolder(folder());
0125     bkGroup.setIcon(m_icon);
0126     m_group = bkGroup.address();
0127 }
0128 
0129 void ImportCommand::redo()
0130 {
0131     KBookmarkGroup bkGroup;
0132 
0133     if (!folder().isNull()) {
0134         doCreateHoldingFolder(bkGroup);
0135 
0136     } else {
0137         // import into the root, after cleaning it up
0138         bkGroup = GlobalBookmarkManager::self()->root();
0139         delete m_cleanUpCmd;
0140         m_cleanUpCmd = DeleteCommand::deleteAll(m_model, bkGroup);
0141 
0142         new DeleteCommand(m_model, bkGroup.address(), true /* contentOnly */, m_cleanUpCmd);
0143         m_cleanUpCmd->redo();
0144 
0145         // import at the root
0146         m_group = QLatin1String("");
0147     }
0148 
0149     doExecute(bkGroup);
0150 
0151     // notify the model that the data has changed
0152     //
0153     // FIXME Resetting the model completely has the unwanted
0154     // side-effect of collapsing all items in tree views
0155     // (and possibly other side effects)
0156     m_model->resetModel();
0157 }
0158 
0159 void ImportCommand::undo()
0160 {
0161     if (!folder().isEmpty()) {
0162         // we created a group -> just delete it
0163         DeleteCommand cmd(m_model, m_group);
0164         cmd.redo();
0165 
0166     } else {
0167         // we imported at the root -> delete everything
0168         KBookmarkGroup root = GlobalBookmarkManager::self()->root();
0169         QUndoCommand *cmd = DeleteCommand::deleteAll(m_model, root);
0170 
0171         cmd->redo();
0172         delete cmd;
0173 
0174         // and recreate what was there before
0175         m_cleanUpCmd->undo();
0176     }
0177 }
0178 
0179 QString ImportCommand::affectedBookmarks() const
0180 {
0181     QString rootAdr = GlobalBookmarkManager::self()->root().address();
0182     if (m_group == rootAdr)
0183         return m_group;
0184     else
0185         return KBookmark::parentAddress(m_group);
0186 }
0187 
0188 /* -------------------------------------- */
0189 
0190 QString MozImportCommand::requestFilename() const
0191 {
0192     static KMozillaBookmarkImporterImpl importer;
0193     return importer.findDefaultLocation();
0194 }
0195 
0196 QString NSImportCommand::requestFilename() const
0197 {
0198     static KNSBookmarkImporterImpl importer;
0199     return importer.findDefaultLocation();
0200 }
0201 
0202 QString OperaImportCommand::requestFilename() const
0203 {
0204     static KOperaBookmarkImporterImpl importer;
0205     return importer.findDefaultLocation();
0206 }
0207 
0208 QString IEImportCommand::requestFilename() const
0209 {
0210     static KIEBookmarkImporterImpl importer;
0211     return importer.findDefaultLocation();
0212 }
0213 
0214 // following two are really just xbel
0215 
0216 QString GaleonImportCommand::requestFilename() const
0217 {
0218     return QFileDialog::getOpenFileName(KEBApp::self(),
0219                                         QString(),
0220                                         QString(QDir::homePath() + QStringLiteral("/.galeon")),
0221                                         i18n("Galeon Bookmark Files (*.xbel)"));
0222 }
0223 
0224 QString KDE2ImportCommand::requestFilename() const
0225 {
0226     return QFileDialog::getOpenFileName(KEBApp::self(),
0227                                         QString(),
0228                                         QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/konqueror"),
0229                                         i18n("KDE Bookmark Files (*.xml)"));
0230 }
0231 
0232 /* -------------------------------------- */
0233 
0234 static void parseInto(const KBookmarkGroup &bkGroup, KBookmarkImporterBase *importer)
0235 {
0236     KBookmarkDomBuilder builder(bkGroup, GlobalBookmarkManager::self()->mgr());
0237     builder.connectImporter(importer);
0238     importer->parse();
0239 }
0240 
0241 void OperaImportCommand::doExecute(const KBookmarkGroup &bkGroup)
0242 {
0243     KOperaBookmarkImporterImpl importer;
0244     importer.setFilename(m_fileName);
0245     parseInto(bkGroup, &importer);
0246 }
0247 
0248 void IEImportCommand::doExecute(const KBookmarkGroup &bkGroup)
0249 {
0250     KIEBookmarkImporterImpl importer;
0251     importer.setFilename(m_fileName);
0252     parseInto(bkGroup, &importer);
0253 }
0254 
0255 void HTMLImportCommand::doExecute(const KBookmarkGroup &bkGroup)
0256 {
0257     KNSBookmarkImporterImpl importer;
0258     importer.setFilename(m_fileName);
0259     importer.setUtf8(m_utf8);
0260     parseInto(bkGroup, &importer);
0261 }
0262 
0263 /* -------------------------------------- */
0264 
0265 void XBELImportCommand::doCreateHoldingFolder(KBookmarkGroup &)
0266 {
0267     // rather than reuse the old group node we transform the
0268     // root xbel node into the group when doing an xbel import
0269 }
0270 
0271 void XBELImportCommand::doExecute(const KBookmarkGroup & /*bkGroup*/)
0272 {
0273     // check if already open first???
0274     KBookmarkManager *pManager = KBookmarkManager::managerForFile(m_fileName, QString());
0275 
0276     QDomDocument doc = GlobalBookmarkManager::self()->mgr()->internalDocument();
0277 
0278     // get the xbel
0279     QDomNode subDoc = pManager->internalDocument().namedItem(QStringLiteral("xbel")).cloneNode();
0280     if (subDoc.isProcessingInstruction())
0281         subDoc = subDoc.nextSibling();
0282     if (subDoc.isDocumentType())
0283         subDoc = subDoc.nextSibling();
0284     if (subDoc.nodeName() != QLatin1String("xbel"))
0285         return;
0286 
0287     if (!folder().isEmpty()) {
0288         // transform into folder
0289         subDoc.toElement().setTagName(QStringLiteral("folder"));
0290 
0291         // clear attributes
0292         QStringList tags;
0293         for (int i = 0; i < subDoc.attributes().count(); i++)
0294             tags << subDoc.attributes().item(i).toAttr().name();
0295         for (QStringList::const_iterator it = tags.constBegin(); it != tags.constEnd(); ++it)
0296             subDoc.attributes().removeNamedItem((*it));
0297 
0298         subDoc.toElement().setAttribute(QStringLiteral("icon"), m_icon);
0299 
0300         // give the folder a name
0301         QDomElement textElem = doc.createElement(QStringLiteral("title"));
0302         subDoc.insertBefore(textElem, subDoc.firstChild());
0303         textElem.appendChild(doc.createTextNode(folder()));
0304     }
0305 
0306     // import and add it
0307     QDomNode node = doc.importNode(subDoc, true);
0308 
0309     if (!folder().isEmpty()) {
0310         GlobalBookmarkManager::self()->root().internalElement().appendChild(node);
0311         m_group = KBookmarkGroup(node.toElement()).address();
0312 
0313     } else {
0314         QDomElement root = GlobalBookmarkManager::self()->root().internalElement();
0315 
0316         QList<QDomElement> childList;
0317 
0318         QDomNode n = subDoc.firstChild().toElement();
0319         while (!n.isNull()) {
0320             QDomElement e = n.toElement();
0321             if (!e.isNull())
0322                 childList.append(e);
0323             n = n.nextSibling();
0324         }
0325 
0326         QList<QDomElement>::Iterator it = childList.begin();
0327         QList<QDomElement>::Iterator end = childList.end();
0328         for (; it != end; ++it)
0329             root.appendChild((*it));
0330     }
0331 }