1 /***************************************************************************
2 * Copyright (C) 2003 by S�astien Laot *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
22 #include <qstringlist.h>
24 #include <qfileinfo.h>
27 #include <Q3TextStream>
28 #include <kglobalsettings.h>
29 #include <kmessagebox.h>
31 #include <kapplication.h>
35 #include "formatimporter.h"
36 #include "notecontent.h"
37 #include "notefactory.h"
44 bool FormatImporter::shouldImportBaskets()
46 // We should import if the application have not successfully loaded any basket...
47 if (Global::bnpView
->firstListViewItem())
50 // ... And there is at least one folder in the save folder, with a ".basket" file inside that folder.
51 QDir
dir(Global::savesFolder(), QString::null
, QDir::Name
| QDir::IgnoreCase
, QDir::Dirs
| QDir::NoSymLinks
);
52 QStringList list
= dir
.entryList();
53 for (QStringList::Iterator it
= list
.begin(); it
!= list
.end(); ++it
)
54 if (*it
!= "." && *it
!= ".." && dir
.exists(Global::savesFolder() + *it
+ "/.basket"))
60 void FormatImporter::copyFolder(const QString
&folder
, const QString
&newFolder
)
63 KIO::CopyJob
*copyJob
= KIO::copyAs(KUrl(folder
), KUrl(newFolder
), /*showProgressInfo=*/false);
64 connect( copyJob
, SIGNAL(result(KIO::Job
*)), this, SLOT(slotCopyingDone(KIO::Job
*)) );
66 kapp
->processEvents();
69 void FormatImporter::moveFolder(const QString
&folder
, const QString
&newFolder
)
72 KIO::CopyJob
*copyJob
= KIO::moveAs(KUrl(folder
), KUrl(newFolder
), /*showProgressInfo=*/false);
73 connect( copyJob
, SIGNAL(result(KIO::Job
*)), this, SLOT(slotCopyingDone(KIO::Job
*)) );
75 kapp
->processEvents();
78 void FormatImporter::slotCopyingDone(KIO::Job
*)
80 // std::cout << "Copy finished of " + from.path() + " to " + to.path() << std::endl;
84 void FormatImporter::importBaskets()
86 std::cout
<< "Import Baskets: Preparing..." << std::endl
;
88 // Some preliminary preparations (create the destination folders and the basket tree file):
90 dirPrep
.mkdir(Global::savesFolder());
91 dirPrep
.mkdir(Global::basketsFolder());
92 QDomDocument
document("basketTree");
93 QDomElement root
= document
.createElement("basketTree");
94 document
.appendChild(root
);
96 // First up, establish a list of every baskets, ensure the old order (if any), and count them.
99 // Read the 0.5.0 baskets order:
100 QDomDocument
*doc
= XMLWork::openFile("container", Global::savesFolder() + "container.baskets");
102 QDomElement docElem
= doc
->documentElement();
103 QDomElement basketsElem
= XMLWork::getElement(docElem
, "baskets");
104 QDomNode n
= basketsElem
.firstChild();
105 while (!n
.isNull()) {
106 QDomElement e
= n
.toElement();
107 if ((!e
.isNull()) && e
.tagName() == "basket")
108 baskets
.append(e
.text());
113 // Then load the baskets that weren't loaded (import < 0.5.0 ones):
114 QDir
dir(Global::savesFolder(), QString::null
, QDir::Name
| QDir::IgnoreCase
, QDir::Dirs
| QDir::NoSymLinks
);
115 QStringList list
= dir
.entryList();
116 if (list
.count() > 2) // Pass "." and ".."
117 for (QStringList::Iterator it
= list
.begin(); it
!= list
.end(); ++it
) // For each folder
118 if (*it
!= "." && *it
!= ".." && dir
.exists(Global::savesFolder() + *it
+ "/.basket")) // If it can be a basket folder
119 if ( baskets
.find((*it
) + "/") == baskets
.end() &&
120 baskets
.find(*it
) == baskets
.end() ) // And if it is not already in the imported baskets list
123 std::cout
<< "Import Baskets: Found " << baskets
.count() << " baskets to import." << std::endl
;
125 // Import every baskets:
127 for (QStringList::iterator it
= baskets
.begin(); it
!= baskets
.end(); ++it
) {
129 std::cout
<< "Import Baskets: Importing basket " << i
<< " of " << baskets
.count() << "..." << std::endl
;
131 // Move the folder to the new repository (normal basket) or copy the folder (mirorred folder):
132 QString folderName
= *it
;
133 if (folderName
.startsWith("/")) { // It was a folder mirror:
134 KMessageBox::information(0, i18n("<p>Folder mirroring is not possible anymore (see <a href='http://basket.kde.org/'>basket.kde.org</a> for more information).</p>"
135 "<p>The folder <b>%1</b> has been copied for the basket needs. You can either delete this folder or delete the basket, or use both. But remember that "
136 "modifying one will not modify the other anymore as they are now separate entities.</p>").arg(folderName
), i18n("Folder Mirror Import"),
137 "", KMessageBox::AllowLink
);
138 // Also modify folderName to be only the folder name and not the full path anymore:
139 QString newFolderName
= folderName
;
140 if (newFolderName
.endsWith("/"))
141 newFolderName
= newFolderName
.left(newFolderName
.length() - 1);
142 newFolderName
= newFolderName
.mid(newFolderName
.findRev('/') + 1);
143 newFolderName
= Tools::fileNameForNewFile(newFolderName
, Global::basketsFolder());
145 f
.copyFolder(folderName
, Global::basketsFolder() + newFolderName
);
146 folderName
= newFolderName
;
148 dir
.rename(Global::savesFolder() + folderName
, Global::basketsFolder() + folderName
); // Move the folder
150 // Import the basket structure file and get the properties (to add them in the tree basket-properties cache):
151 QDomElement properties
= importBasket(folderName
);
153 // Add it to the XML document:
154 QDomElement basketElement
= document
.createElement("basket");
155 root
.appendChild(basketElement
);
156 basketElement
.setAttribute("folderName", folderName
);
157 basketElement
.appendChild(properties
);
160 // Finalize (write to disk and delete now useless files):
161 std::cout
<< "Import Baskets: Finalizing..." << std::endl
;
163 QFile
file(Global::basketsFolder() + "baskets.xml");
164 if (file
.open(QIODevice::WriteOnly
)) {
165 Q3TextStream
stream(&file
);
166 stream
.setEncoding(Q3TextStream::UnicodeUTF8
);
167 QString xml
= document
.toString();
168 stream
<< "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
173 Tools::deleteRecursively(Global::savesFolder() + ".tmp");
174 dir
.remove(Global::savesFolder() + "container.baskets");
176 std::cout
<< "Import Baskets: Finished." << std::endl
;
179 QDomElement
FormatImporter::importBasket(const QString
&folderName
)
181 // Load the XML file:
182 QDomDocument
*document
= XMLWork::openFile("basket", Global::basketsFolder() + folderName
+ "/.basket");
184 std::cout
<< "Import Baskets: Failed to read the basket file!" << std::endl
;
185 return QDomElement();
187 QDomElement docElem
= document
->documentElement();
189 // Import properties (change <background color=""> to <appearance backgroundColor="">, and figure out if is a checklist or not):
190 QDomElement properties
= XMLWork::getElement(docElem
, "properties");
191 QDomElement background
= XMLWork::getElement(properties
, "background");
192 QColor backgroundColor
= QColor(background
.attribute("color"));
193 if (backgroundColor
.isValid() && (backgroundColor
!= KGlobalSettings::baseColor())) { // Use the default color if it was already that color:
194 QDomElement appearance
= document
->createElement("appearance");
195 appearance
.setAttribute("backgroundColor", backgroundColor
.name());
196 properties
.appendChild(appearance
);
198 QDomElement disposition
= document
->createElement("disposition");
199 disposition
.setAttribute("mindMap", "false");
200 disposition
.setAttribute("columnCount", "1");
201 disposition
.setAttribute("free", "false");
202 bool isCheckList
= XMLWork::trueOrFalse( XMLWork::getElementText(properties
, "showCheckBoxes", false) );
204 // Insert all notes in a group (column): 1/ rename "items" to "group", 2/ add "notes" to root, 3/ move "group" into "notes"
205 QDomElement column
= XMLWork::getElement(docElem
, "items");
206 column
.setTagName("group");
207 QDomElement notes
= document
->createElement("notes");
208 notes
.appendChild(column
);
209 docElem
.appendChild(notes
);
211 // Import notes from older representations:
212 QDomNode n
= column
.firstChild();
213 while ( ! n
.isNull() ) {
214 QDomElement e
= n
.toElement();
216 e
.setTagName("note");
217 QDomElement content
= XMLWork::getElement(e
, "content");
220 bool isChecked
= XMLWork::trueOrFalse(e
.attribute("checked", "false"));
221 XMLWork::addElement(*document
, e
, "tags", (isChecked
? "todo_done" : "todo_unchecked"));
223 // Import annotations as folded groups:
224 QDomElement parentE
= column
;
225 QString annotations
= XMLWork::getElementText(e
, "annotations", "");
226 if (!annotations
.isEmpty()) {
227 QDomElement annotGroup
= document
->createElement("group");
228 column
.insertBefore(annotGroup
, e
);
229 annotGroup
.setAttribute("folded", "true");
230 annotGroup
.appendChild(e
);
231 parentE
= annotGroup
;
232 // Create the text note and add it to the DOM tree:
233 QDomElement annotNote
= document
->createElement("note");
234 annotNote
.setAttribute("type", "text");
235 annotGroup
.appendChild(annotNote
);
236 QString annotFileName
= Tools::fileNameForNewFile("annotations1.txt", Basket::fullPathForFolderName(folderName
));
237 QString annotFullPath
= Basket::fullPathForFolderName(folderName
) + "/" + annotFileName
;
238 QFile
file(annotFullPath
);
239 if (file
.open(QIODevice::WriteOnly
)) {
240 Q3TextStream
stream(&file
);
241 stream
<< annotations
;
244 XMLWork::addElement(*document
, annotNote
, "content", annotFileName
);
247 // Import Launchers from 0.3.x, 0.4.0 and 0.5.0-alphas:
248 QString runCommand
= e
.attribute("runcommand"); // Keep compatibility with 0.4.0 and 0.5.0-alphas versions
249 runCommand
= XMLWork::getElementText(e
, "action", runCommand
); // Keep compatibility with 0.3.x versions
250 if ( ! runCommand
.isEmpty() ) { // An import should be done
251 // Prepare the launcher note:
252 QString title
= content
.attribute("title", "");
253 QString icon
= content
.attribute("icon", "");
254 if (title
.isEmpty()) title
= runCommand
;
255 if (icon
.isEmpty()) icon
= NoteFactory::iconForCommand(runCommand
);
256 // Import the launcher note:
257 // Adapted version of "QString launcherName = NoteFactory::createNoteLauncherFile(runCommand, title, icon, this)":
258 QString launcherContent
= QString(
264 "Type=Application\n").arg(runCommand
, title
, icon
.isEmpty() ? QString("exec") : icon
);
265 QString launcherFileName
= Tools::fileNameForNewFile("launcher.desktop", Global::basketsFolder() + folderName
/*+ "/"*/);
266 QString launcherFullPath
= Global::basketsFolder() + folderName
/*+ "/"*/ + launcherFileName
;
267 QFile
file(launcherFullPath
);
268 if (file
.open(QIODevice::WriteOnly
)) {
269 Q3TextStream
stream(&file
);
270 stream
.setEncoding(Q3TextStream::UnicodeUTF8
);
271 stream
<< launcherContent
;
274 // Add the element to the DOM:
275 QDomElement launcherElem
= document
->createElement("note");
276 parentE
.insertBefore(launcherElem
, e
);
277 launcherElem
.setAttribute("type", "launcher");
278 XMLWork::addElement(*document
, launcherElem
, "content", launcherFileName
);
280 // Import unknown ns to 0.6.0:
281 if (e
.attribute("type") == "unknow")
282 e
.setAttribute("type", "unknown");
283 // Import links from version < 0.5.0:
284 if (!content
.attribute("autotitle").isEmpty() && content
.attribute("autoTitle").isEmpty())
285 content
.setAttribute("autoTitle", content
.attribute("autotitle"));
286 if (!content
.attribute("autoicon").isEmpty() && content
.attribute("autoIcon").isEmpty())
287 content
.setAttribute("autoIcon", content
.attribute("autoicon"));
292 // Save the resulting XML file:
293 QFile
file(Global::basketsFolder() + folderName
+ "/.basket");
294 if (file
.open(QIODevice::WriteOnly
)) {
295 Q3TextStream
stream(&file
);
296 stream
.setEncoding(Q3TextStream::UnicodeUTF8
);
297 // QString xml = document->toString();
298 // stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n";
300 stream
<< document
->toString(); // Document is ALREADY using UTF-8
303 std::cout
<< "Import Baskets: Failed to save the basket file!" << std::endl
;
305 // Return the newly created properties (to put in the basket tree):
309 #include "formatimporter.moc"