File indexing completed on 2024-04-21 05:50:22

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 
0031 #include <QFileDialog>
0032 #include <QStandardPaths>
0033 
0034 #include <KBookmark>
0035 #include <KBookmarkManager>
0036 #include <KMessageBox>
0037 
0038 #include "kbookmarkimporter.h"
0039 #include "kbookmarkimporter_ie.h"
0040 #include "kbookmarkimporter_ns.h"
0041 #include "kbookmarkimporter_opera.h"
0042 #include <kbookmarkdombuilder.h>
0043 #include <kwidgetsaddons_version.h>
0044 
0045 ImportCommand::ImportCommand(KBookmarkModel *model)
0046     : QUndoCommand()
0047     , m_model(model)
0048     , m_utf8(false)
0049     , m_folder(false)
0050     , m_cleanUpCmd(nullptr)
0051 {
0052 }
0053 
0054 void ImportCommand::setVisibleName(const QString &visibleName)
0055 {
0056     m_visibleName = visibleName;
0057     setText(i18nc("(qtundo-format)", "Import %1 Bookmarks", visibleName));
0058 }
0059 
0060 QString ImportCommand::folder() const
0061 {
0062     return m_folder ? i18n("%1 Bookmarks", visibleName()) : QString();
0063 }
0064 
0065 ImportCommand *ImportCommand::importerFactory(KBookmarkModel *model, const QString &type)
0066 {
0067     if (type == QLatin1String("Galeon"))
0068         return new GaleonImportCommand(model);
0069     else if (type == QLatin1String("IE"))
0070         return new IEImportCommand(model);
0071     else if (type == QLatin1String("KDE2"))
0072         return new KDE2ImportCommand(model);
0073     else if (type == QLatin1String("Opera"))
0074         return new OperaImportCommand(model);
0075     // else if (type == "Crashes") return new CrashesImportCommand();
0076     else if (type == QLatin1String("Moz"))
0077         return new MozImportCommand(model);
0078     else if (type == QLatin1String("NS"))
0079         return new NSImportCommand(model);
0080     else {
0081         qCCritical(KEDITBOOKMARKS_LOG) << "ImportCommand::importerFactory() - invalid type (" << type << ")!";
0082         return nullptr;
0083     }
0084 }
0085 
0086 ImportCommand *ImportCommand::performImport(KBookmarkModel *model, const QString &type, QWidget *top)
0087 {
0088     ImportCommand *importer = ImportCommand::importerFactory(model, type);
0089 
0090     Q_ASSERT(importer);
0091 
0092     QString mydirname = importer->requestFilename();
0093     if (mydirname.isEmpty()) {
0094         delete importer;
0095         return nullptr;
0096     }
0097 
0098     int answer = KMessageBox::questionTwoActionsCancel(top,
0099                                                        i18n("Import as a new subfolder or replace all the current bookmarks?"),
0100                                                        i18nc("@title:window", "%1 Import", importer->visibleName()),
0101                                                        KGuiItem(i18n("As New Folder")),
0102                                                        KGuiItem(i18n("Replace")));
0103 
0104     if (answer == KMessageBox::Cancel) {
0105         delete importer;
0106         return nullptr;
0107     }
0108 
0109     importer->import(mydirname, answer == KMessageBox::ButtonCode::PrimaryAction);
0110     return importer;
0111 }
0112 
0113 void ImportCommand::doCreateHoldingFolder(KBookmarkGroup &bkGroup)
0114 {
0115     bkGroup = GlobalBookmarkManager::self()->mgr()->root().createNewFolder(folder());
0116     bkGroup.setIcon(m_icon);
0117     m_group = bkGroup.address();
0118 }
0119 
0120 void ImportCommand::redo()
0121 {
0122     KBookmarkGroup bkGroup;
0123 
0124     if (!folder().isNull()) {
0125         doCreateHoldingFolder(bkGroup);
0126 
0127     } else {
0128         // import into the root, after cleaning it up
0129         bkGroup = GlobalBookmarkManager::self()->root();
0130         delete m_cleanUpCmd;
0131         m_cleanUpCmd = DeleteCommand::deleteAll(m_model, bkGroup);
0132 
0133         new DeleteCommand(m_model, bkGroup.address(), true /* contentOnly */, m_cleanUpCmd);
0134         m_cleanUpCmd->redo();
0135 
0136         // import at the root
0137         m_group = QLatin1String("");
0138     }
0139 
0140     doExecute(bkGroup);
0141 
0142     // notify the model that the data has changed
0143     //
0144     // FIXME Resetting the model completely has the unwanted
0145     // side-effect of collapsing all items in tree views
0146     // (and possibly other side effects)
0147     m_model->resetModel();
0148 }
0149 
0150 void ImportCommand::undo()
0151 {
0152     if (!folder().isEmpty()) {
0153         // we created a group -> just delete it
0154         DeleteCommand cmd(m_model, m_group);
0155         cmd.redo();
0156 
0157     } else {
0158         // we imported at the root -> delete everything
0159         KBookmarkGroup root = GlobalBookmarkManager::self()->root();
0160         QUndoCommand *cmd = DeleteCommand::deleteAll(m_model, root);
0161 
0162         cmd->redo();
0163         delete cmd;
0164 
0165         // and recreate what was there before
0166         m_cleanUpCmd->undo();
0167     }
0168 }
0169 
0170 QString ImportCommand::affectedBookmarks() const
0171 {
0172     QString rootAdr = GlobalBookmarkManager::self()->root().address();
0173     if (m_group == rootAdr)
0174         return m_group;
0175     else
0176         return KBookmark::parentAddress(m_group);
0177 }
0178 
0179 /* -------------------------------------- */
0180 
0181 QString MozImportCommand::requestFilename() const
0182 {
0183     static KMozillaBookmarkImporterImpl importer;
0184     return importer.findDefaultLocation();
0185 }
0186 
0187 QString NSImportCommand::requestFilename() const
0188 {
0189     static NSBookmarkImporterImpl importer;
0190     return importer.findDefaultLocation();
0191 }
0192 
0193 QString OperaImportCommand::requestFilename() const
0194 {
0195     static OperaBookmarkImporterImpl importer;
0196     return importer.findDefaultLocation();
0197 }
0198 
0199 QString IEImportCommand::requestFilename() const
0200 {
0201     static IEBookmarkImporterImpl importer;
0202     return importer.findDefaultLocation();
0203 }
0204 
0205 // following two are really just xbel
0206 
0207 QString GaleonImportCommand::requestFilename() const
0208 {
0209     return QFileDialog::getOpenFileName(KEBApp::self(),
0210                                         QString(),
0211                                         QString(QDir::homePath() + QStringLiteral("/.galeon")),
0212                                         i18n("Galeon Bookmark Files (*.xbel)"));
0213 }
0214 
0215 QString KDE2ImportCommand::requestFilename() const
0216 {
0217     return QFileDialog::getOpenFileName(KEBApp::self(),
0218                                         QString(),
0219                                         QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/konqueror"),
0220                                         i18n("KDE Bookmark Files (*.xml)"));
0221 }
0222 
0223 /* -------------------------------------- */
0224 
0225 static void parseInto(const KBookmarkGroup &bkGroup, BookmarkImporterBase *importer)
0226 {
0227     BookmarkDomBuilder builder(bkGroup);
0228     builder.connectImporter(importer);
0229     importer->parse();
0230 }
0231 
0232 void OperaImportCommand::doExecute(const KBookmarkGroup &bkGroup)
0233 {
0234     OperaBookmarkImporterImpl importer;
0235     importer.setFilename(m_fileName);
0236     parseInto(bkGroup, &importer);
0237 }
0238 
0239 void IEImportCommand::doExecute(const KBookmarkGroup &bkGroup)
0240 {
0241     IEBookmarkImporterImpl importer;
0242     importer.setFilename(m_fileName);
0243     parseInto(bkGroup, &importer);
0244 }
0245 
0246 void HTMLImportCommand::doExecute(const KBookmarkGroup &bkGroup)
0247 {
0248     NSBookmarkImporterImpl importer;
0249     importer.setFilename(m_fileName);
0250     importer.setUtf8(m_utf8);
0251     parseInto(bkGroup, &importer);
0252 }
0253 
0254 /* -------------------------------------- */
0255 
0256 void XBELImportCommand::doCreateHoldingFolder(KBookmarkGroup &)
0257 {
0258     // rather than reuse the old group node we transform the
0259     // root xbel node into the group when doing an xbel import
0260 }
0261 
0262 void XBELImportCommand::doExecute(const KBookmarkGroup & /*bkGroup*/)
0263 {
0264     // check if already open first???
0265     KBookmarkManager pManager(m_fileName);
0266 
0267     QDomDocument doc = GlobalBookmarkManager::self()->mgr()->internalDocument();
0268 
0269     // get the xbel
0270     QDomNode subDoc = pManager.internalDocument().namedItem(QStringLiteral("xbel")).cloneNode();
0271     if (subDoc.isProcessingInstruction())
0272         subDoc = subDoc.nextSibling();
0273     if (subDoc.isDocumentType())
0274         subDoc = subDoc.nextSibling();
0275     if (subDoc.nodeName() != QLatin1String("xbel"))
0276         return;
0277 
0278     if (!folder().isEmpty()) {
0279         // transform into folder
0280         subDoc.toElement().setTagName(QStringLiteral("folder"));
0281 
0282         // clear attributes
0283         QStringList tags;
0284         for (int i = 0; i < subDoc.attributes().count(); i++)
0285             tags << subDoc.attributes().item(i).toAttr().name();
0286         for (QStringList::const_iterator it = tags.constBegin(); it != tags.constEnd(); ++it)
0287             subDoc.attributes().removeNamedItem((*it));
0288 
0289         subDoc.toElement().setAttribute(QStringLiteral("icon"), m_icon);
0290 
0291         // give the folder a name
0292         QDomElement textElem = doc.createElement(QStringLiteral("title"));
0293         subDoc.insertBefore(textElem, subDoc.firstChild());
0294         textElem.appendChild(doc.createTextNode(folder()));
0295     }
0296 
0297     // import and add it
0298     QDomNode node = doc.importNode(subDoc, true);
0299 
0300     if (!folder().isEmpty()) {
0301         GlobalBookmarkManager::self()->root().internalElement().appendChild(node);
0302         m_group = KBookmarkGroup(node.toElement()).address();
0303 
0304     } else {
0305         QDomElement root = GlobalBookmarkManager::self()->root().internalElement();
0306 
0307         QList<QDomElement> childList;
0308 
0309         QDomNode n = subDoc.firstChild().toElement();
0310         while (!n.isNull()) {
0311             QDomElement e = n.toElement();
0312             if (!e.isNull())
0313                 childList.append(e);
0314             n = n.nextSibling();
0315         }
0316 
0317         QList<QDomElement>::Iterator it = childList.begin();
0318         QList<QDomElement>::Iterator end = childList.end();
0319         for (; it != end; ++it)
0320             root.appendChild((*it));
0321     }
0322 }
0323 
0324 #include "moc_importers.cpp"