summaryrefslogtreecommitdiffstats
path: root/src/notedrag.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-10 00:18:25 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-10 00:18:25 +0000
commitf21e5792b5084f5d008bf46f6316030c6dfb31e5 (patch)
treed51583b36aa1672bac78d98a682cdc330df27e4d /src/notedrag.cpp
downloadbasket-f21e5792b5084f5d008bf46f6316030c6dfb31e5.tar.gz
basket-f21e5792b5084f5d008bf46f6316030c6dfb31e5.zip
Add author-abandoned basket application
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/basket@1072339 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/notedrag.cpp')
-rw-r--r--src/notedrag.cpp593
1 files changed, 593 insertions, 0 deletions
diff --git a/src/notedrag.cpp b/src/notedrag.cpp
new file mode 100644
index 0000000..633dec2
--- /dev/null
+++ b/src/notedrag.cpp
@@ -0,0 +1,593 @@
+/***************************************************************************
+ * Copyright (C) 2003 by S�astien Laot *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qdragobject.h>
+#include <qdir.h>
+#include <qpainter.h>
+#include <qtextcodec.h>
+#include <qbuffer.h>
+#include <kurldrag.h>
+#include <kdeversion.h>
+#include <kapplication.h>
+#include <qdesktopwidget.h>
+
+#include "basket.h"
+#include "notedrag.h"
+#include "notefactory.h"
+#include "tools.h"
+#include "global.h"
+
+#include <iostream>
+
+/** NoteDrag */
+
+const char * NoteDrag::NOTE_MIME_STRING = "application/x-basket-note";
+
+void NoteDrag::createAndEmptyCuttingTmpFolder()
+{
+ Tools::deleteRecursively(Global::tempCutFolder());
+ QDir dir;
+ dir.mkdir(Global::tempCutFolder());
+}
+
+QDragObject* NoteDrag::dragObject(NoteSelection *noteList, bool cutting, QWidget *source)
+{
+ if (noteList->count() <= 0)
+ return 0;
+
+ // The MimeSource:
+ KMultipleDrag *multipleDrag = new KMultipleDrag(source);
+
+ // Make sure the temporary folder exists and is empty (we delete previously moved file(s) (if exists)
+ // since we override the content of the clipboard and previous file willn't be accessable anymore):
+ createAndEmptyCuttingTmpFolder();
+
+ // The "Native Format" Serialization:
+ QBuffer buffer;
+ if (buffer.open(IO_WriteOnly)) {
+ QDataStream stream(&buffer);
+ // First append a pointer to the basket:
+ stream << (Q_UINT64)(noteList->firstStacked()->note->basket());
+ // Then a list of pointers to all notes, and parent groups:
+ for (NoteSelection *node = noteList->firstStacked(); node; node = node->nextStacked())
+ stream << (Q_UINT64)(node->note);
+ QValueList<Note*> groups = noteList->parentGroups();
+ for (QValueList<Note*>::iterator it = groups.begin(); it != groups.end(); ++it)
+ stream << (Q_UINT64)(*it);
+ stream << (Q_UINT64)0;
+ // And finally the notes themselves:
+ serializeNotes(noteList, stream, cutting);
+ // Append the object:
+ buffer.close();
+ QStoredDrag *dragObject = new QStoredDrag(NOTE_MIME_STRING, source);
+ dragObject->setEncodedData(buffer.buffer());
+ multipleDrag->addDragObject(dragObject);
+ }
+
+ // The "Other Flavours" Serialization:
+ serializeText( noteList, multipleDrag );
+ serializeHtml( noteList, multipleDrag );
+ serializeImage( noteList, multipleDrag );
+ serializeLinks( noteList, multipleDrag, cutting );
+
+ // The Alternate Flavours:
+ if (noteList->count() == 1)
+ noteList->firstStacked()->note->content()->addAlternateDragObjects(multipleDrag);
+
+ // If it is a drag, and not a copy/cut, add the feedback pixmap:
+ if (source)
+ setFeedbackPixmap(noteList, multipleDrag);
+
+ return multipleDrag;
+}
+
+void NoteDrag::serializeNotes(NoteSelection *noteList, QDataStream &stream, bool cutting)
+{
+ for (NoteSelection *node = noteList; node; node = node->next) {
+ stream << (Q_UINT64)(node->note);
+ if (node->firstChild) {
+ stream << (Q_UINT64)(NoteType::Group) << (Q_UINT64)(node->note->groupWidth()) << (Q_UINT64)(node->note->isFolded());
+ serializeNotes(node->firstChild, stream, cutting);
+ } else {
+ NoteContent *content = node->note->content();
+ stream << (Q_UINT64)(content->type()) << (Q_UINT64)(node->note->groupWidth());
+ // Serialize file name, and move the file to a temporary place if the note is to be cuttted.
+ // If note does not have file name, we append empty string to be able to easily decode the notes later:
+ stream << content->fileName();
+ if (content->shouldSerializeFile()) {
+ if (cutting) {
+ // Move file in a temporary place:
+ QString fullPath = Global::tempCutFolder() + Tools::fileNameForNewFile(content->fileName(), Global::tempCutFolder());
+ KIO::move(KURL(content->fullPath()), KURL(fullPath), /*showProgressInfo=*/false);
+ node->fullPath = fullPath;
+ stream << fullPath;
+ } else
+ stream << content->fullPath();
+ } else
+ stream << QString("");
+ stream << content->note()->addedDate() << content->note()->lastModificationDate();
+ content->serialize(stream);
+ State::List states = node->note->states();
+ for (State::List::Iterator it = states.begin(); it != states.end(); ++it)
+ stream << (Q_UINT64)(*it);
+ stream << (Q_UINT64)0;
+ }
+ }
+ stream << (Q_UINT64)0; // Mark the end of the notes in this group/hierarchy.
+}
+
+void NoteDrag::serializeText(NoteSelection *noteList, KMultipleDrag *multipleDrag)
+{
+ QString textEquivalent;
+ QString text;
+ for (NoteSelection *node = noteList->firstStacked(); node; node = node->nextStacked()) {
+ text = node->note->toText(node->fullPath); // note->toText() and not note->content()->toText() because the first one will also export the tags as text.
+ if (!text.isEmpty())
+ textEquivalent += (!textEquivalent.isEmpty() ? "\n" : "") + text;
+ }
+ if (!textEquivalent.isEmpty())
+ multipleDrag->addDragObject( new QTextDrag(textEquivalent) );
+}
+
+void NoteDrag::serializeHtml(NoteSelection *noteList, KMultipleDrag *multipleDrag)
+{
+ QString htmlEquivalent;
+ QString html;
+ for (NoteSelection *node = noteList->firstStacked(); node; node = node->nextStacked()) {
+ html = node->note->content()->toHtml("", node->fullPath);
+ if (!html.isEmpty())
+ htmlEquivalent += (!htmlEquivalent.isEmpty() ? "<br>\n" : "") + html;
+ }
+ if (!htmlEquivalent.isEmpty()) {
+ // Add HTML flavour:
+ QTextDrag *htmlDrag = new QTextDrag(htmlEquivalent);
+ htmlDrag->setSubtype("html");
+ multipleDrag->addDragObject(htmlDrag);
+ // But also QTextEdit flavour, to be able to paste several notes to a text edit:
+ QByteArray byteArray = ("<!--StartFragment--><p>" + htmlEquivalent).local8Bit();
+ QStoredDrag *richTextDrag = new QStoredDrag("application/x-qrichtext");
+ richTextDrag->setEncodedData(byteArray);
+ multipleDrag->addDragObject(richTextDrag);
+ }
+}
+
+void NoteDrag::serializeImage(NoteSelection *noteList, KMultipleDrag *multipleDrag)
+{
+ QValueList<QPixmap> pixmaps;
+ QPixmap pixmap;
+ for (NoteSelection *node = noteList->firstStacked(); node; node = node->nextStacked()) {
+ pixmap = node->note->content()->toPixmap();
+ if (!pixmap.isNull())
+ pixmaps.append(pixmap);
+ }
+ if (!pixmaps.isEmpty()) {
+ QPixmap pixmapEquivalent;
+ if (pixmaps.count() == 1)
+ pixmapEquivalent = pixmaps[0];
+ else {
+ // Search the total size:
+ int height = 0;
+ int width = 0;
+ for (QValueList<QPixmap>::iterator it = pixmaps.begin(); it != pixmaps.end(); ++it) {
+ height += (*it).height();
+ if ((*it).width() > width)
+ width = (*it).width();
+ }
+ // Create the image by painting all image into one big image:
+ pixmapEquivalent.resize(width, height);
+ pixmapEquivalent.fill(Qt::white);
+ QPainter painter(&pixmapEquivalent);
+ height = 0;
+ for (QValueList<QPixmap>::iterator it = pixmaps.begin(); it != pixmaps.end(); ++it) {
+ painter.drawPixmap(0, height, *it);
+ height += (*it).height();
+ }
+ }
+ QImageDrag *imageDrag = new QImageDrag(pixmapEquivalent.convertToImage());
+ multipleDrag->addDragObject(imageDrag);
+ }
+}
+
+void NoteDrag::serializeLinks(NoteSelection *noteList, KMultipleDrag *multipleDrag, bool cutting)
+{
+ KURL::List urls;
+ QStringList titles;
+ KURL url;
+ QString title;
+ for (NoteSelection *node = noteList->firstStacked(); node; node = node->nextStacked()) {
+ node->note->content()->toLink(&url, &title, node->fullPath);
+ if (!url.isEmpty()) {
+ urls.append(url);
+ titles.append(title);
+ }
+ }
+ if (!urls.isEmpty()) {
+ // First, the standard text/uri-list MIME format:
+#if KDE_IS_VERSION( 3, 3, 90 )
+ KURLDrag *urlsDrag = new KURLDrag(urls);
+ // ONLY export as text/uri-list, and not as text/plain* as we wil do that better ourself
+ urlsDrag->setExportAsText(false);
+ multipleDrag->addDragObject(urlsDrag);
+#else
+ KURLDrag2 *urlsDrag = new KURLDrag2(urls);
+ QByteArray byteArray = urlsDrag->encodedData2("text/uri-list");
+ QStoredDrag *uriListDrag = new QStoredDrag("text/uri-list");
+ uriListDrag->setEncodedData(byteArray);
+ multipleDrag->addDragObject(uriListDrag);
+ delete urlsDrag;
+#endif
+ // Then, also provide it in the Mozilla proprietary format (that also allow to add titles to URLs):
+ // A version for Mozilla applications (convert to "theUrl\ntheTitle", into UTF-16):
+ // FIXME: Does Mozilla support the drag of several URLs at once?
+ // FIXME: If no, only provide that if theire is only ONE URL.
+ QString xMozUrl;
+ for (uint i = 0; i < urls.count(); ++i)
+ xMozUrl += (xMozUrl.isEmpty() ? "" : "\n") + urls[i].prettyURL() + "\n" + titles[i];
+/* Code for only one: ===============
+ xMozUrl = note->title() + "\n" + note->url().prettyURL();*/
+ QByteArray baMozUrl;
+ QTextStream stream(baMozUrl, IO_WriteOnly);
+ stream.setEncoding(QTextStream::RawUnicode); // It's UTF16 (aka UCS2), but with the first two order bytes
+ stream << xMozUrl;
+ QStoredDrag *xMozUrlDrag = new QStoredDrag("text/x-moz-url");
+ xMozUrlDrag->setEncodedData(baMozUrl);
+ multipleDrag->addDragObject(xMozUrlDrag);
+
+ if (cutting) {
+ QByteArray arrayCut(2);
+ QStoredDrag *storedDragCut = new QStoredDrag("application/x-kde-cutselection");
+ arrayCut[0] = '1';
+ arrayCut[1] = 0;
+ storedDragCut->setEncodedData(arrayCut);
+ multipleDrag->addDragObject(storedDragCut);
+ }
+ }
+}
+
+void NoteDrag::setFeedbackPixmap(NoteSelection *noteList, KMultipleDrag *multipleDrag)
+{
+ QPixmap pixmap = feedbackPixmap(noteList);
+ if (!pixmap.isNull())
+ multipleDrag->setPixmap(pixmap, QPoint(-8, -8));
+}
+
+QPixmap NoteDrag::feedbackPixmap(NoteSelection *noteList)
+{
+ if (noteList == 0)
+ return QPixmap();
+
+ static const int MARGIN = 2;
+ static const int SPACING = 1;
+
+ QColor textColor = noteList->firstStacked()->note->basket()->textColor();
+ QColor backgroundColor = noteList->firstStacked()->note->basket()->backgroundColor().dark(NoteContent::FEEDBACK_DARKING);
+
+ QValueList<QPixmap> pixmaps;
+ QValueList<QColor> backgrounds;
+ QValueList<bool> spaces;
+ QPixmap pixmap;
+ int height = 0;
+ int width = 0;
+ int i = 0;
+ bool elipsisImage = false;
+ QColor bgColor;
+ bool needSpace;
+ for (NoteSelection *node = noteList->firstStacked(); node; node = node->nextStacked(), ++i) {
+ if (elipsisImage) {
+ pixmap = QPixmap(7, 2);
+ pixmap.fill(backgroundColor);
+ QPainter painter(&pixmap);
+ painter.setPen(textColor);
+ painter.drawPoint(1, 1);
+ painter.drawPoint(3, 1);
+ painter.drawPoint(5, 1);
+ painter.end();
+ bgColor = node->note->basket()->backgroundColor();
+ needSpace = false;
+ } else {
+ pixmap = node->note->content()->feedbackPixmap(/*maxWidth=*/kapp->desktop()->width() / 2, /*maxHeight=*/96);
+ bgColor = node->note->backgroundColor();
+ needSpace = node->note->content()->needSpaceForFeedbackPixmap();
+ }
+ if (!pixmap.isNull()) {
+ if (pixmap.width() > width)
+ width = pixmap.width();
+ pixmaps.append(pixmap);
+ backgrounds.append(bgColor);
+ spaces.append(needSpace);
+ height += (i > 0 && needSpace ? 1 : 0) + pixmap.height() + SPACING + (needSpace ? 1 : 0);
+ if (elipsisImage)
+ break;
+ if (height > kapp->desktop()->height() / 2)
+ elipsisImage = true;
+ }
+ }
+ if (!pixmaps.isEmpty()) {
+ QPixmap result(MARGIN + width + MARGIN, MARGIN + height - SPACING + MARGIN - (spaces.last() ? 1 : 0));
+ QPainter painter(&result);
+ // Draw all the images:
+ height = MARGIN;
+ QValueList<QPixmap>::iterator it;
+ QValueList<QColor>::iterator it2;
+ QValueList<bool>::iterator it3;
+ int i = 0;
+ for (it = pixmaps.begin(), it2 = backgrounds.begin(), it3 = spaces.begin(); it != pixmaps.end(); ++it, ++it2, ++it3, ++i) {
+ if (i != 0 && (*it3)) {
+ painter.fillRect(MARGIN, height, result.width() - 2 * MARGIN, SPACING, (*it2).dark(NoteContent::FEEDBACK_DARKING));
+ ++height;
+ }
+ painter.drawPixmap(MARGIN, height, *it);
+ if ((*it).width() < width)
+ painter.fillRect(MARGIN + (*it).width(), height, width - (*it).width(), (*it).height(), (*it2).dark(NoteContent::FEEDBACK_DARKING));
+ if (*it3) {
+ painter.fillRect(MARGIN, height + (*it).height(), result.width() - 2 * MARGIN, SPACING, (*it2).dark(NoteContent::FEEDBACK_DARKING));
+ ++height;
+ }
+ painter.fillRect(MARGIN, height + (*it).height(), result.width() - 2 * MARGIN, SPACING, Tools::mixColor(textColor, backgroundColor));
+ height += (*it).height() + SPACING;
+ }
+ // Draw the border:
+ painter.setPen(textColor);
+ painter.drawLine(0, 0, result.width() - 1, 0);
+ painter.drawLine(0, 0, 0, result.height() - 1);
+ painter.drawLine(0, result.height() - 1, result.width() - 1, result.height() - 1);
+ painter.drawLine(result.width() - 1, 0, result.width() - 1, result.height() - 1);
+ // Draw the "lightly rounded" border:
+ painter.setPen(Tools::mixColor(textColor, backgroundColor));
+ painter.drawPoint(0, 0);
+ painter.drawPoint(0, result.height() - 1);
+ painter.drawPoint(result.width() - 1, result.height() - 1);
+ painter.drawPoint(result.width() - 1, 0);
+ // Draw the background in the margin (the inside will be painted above, anyway):
+ painter.setPen(backgroundColor);
+ painter.drawLine(1, 1, result.width() - 2, 1);
+ painter.drawLine(1, 1, 1, result.height() - 2);
+ painter.drawLine(1, result.height() - 2, result.width() - 2, result.height() - 2);
+ painter.drawLine(result.width() - 2, 1, result.width() - 2, result.height() - 2);
+ // And assign the feedback pixmap to the drag object:
+ //multipleDrag->setPixmap(result, QPoint(-8, -8));
+ return result;
+ }
+ return QPixmap();
+}
+
+bool NoteDrag::canDecode(QMimeSource *source)
+{
+ return source->provides(NOTE_MIME_STRING);
+}
+
+Basket* NoteDrag::basketOf(QMimeSource *source)
+{
+ QBuffer buffer(source->encodedData(NOTE_MIME_STRING));
+ if (buffer.open(IO_ReadOnly)) {
+ QDataStream stream(&buffer);
+ // Get the parent basket:
+ Q_UINT64 basketPointer;
+ stream >> (Q_UINT64&)basketPointer;
+ return (Basket*)basketPointer;
+ } else
+ return 0;
+}
+
+QValueList<Note*> NoteDrag::notesOf(QMimeSource *source)
+{
+ QBuffer buffer(source->encodedData(NOTE_MIME_STRING));
+ if (buffer.open(IO_ReadOnly)) {
+ QDataStream stream(&buffer);
+ // Get the parent basket:
+ Q_UINT64 basketPointer;
+ stream >> (Q_UINT64&)basketPointer;
+ // Get the note list:
+ Q_UINT64 notePointer;
+ QValueList<Note*> notes;
+ do {
+ stream >> notePointer;
+ if (notePointer != 0)
+ notes.append((Note*)notePointer);
+ } while (notePointer);
+ // Done:
+ return notes;
+ } else
+ return QValueList<Note*>();
+}
+
+Note* NoteDrag::decode(QMimeSource *source, Basket *parent, bool moveFiles, bool moveNotes)
+{
+ QBuffer buffer(source->encodedData(NOTE_MIME_STRING));
+ if (buffer.open(IO_ReadOnly)) {
+ QDataStream stream(&buffer);
+ // Get the parent basket:
+ Q_UINT64 basketPointer;
+ stream >> (Q_UINT64&)basketPointer;
+ Basket *basket = (Basket*)basketPointer;
+ // Get the note list:
+ Q_UINT64 notePointer;
+ QValueList<Note*> notes;
+ do {
+ stream >> notePointer;
+ if (notePointer != 0)
+ notes.append((Note*)notePointer);
+ } while (notePointer);
+ // Decode the note hierarchy:
+ Note *hierarchy = decodeHierarchy(stream, parent, moveFiles, moveNotes, basket);
+ // In case we moved notes from one basket to another, save the source basket where notes were removed:
+ basket->filterAgainDelayed(); // Delayed, because if a note is moved to the same basket, the note is not at its
+ basket->save(); // new position yet, and the call to ensureNoteVisible would make the interface flicker!!
+ return hierarchy;
+ } else
+ return 0;
+}
+
+Note* NoteDrag::decodeHierarchy(QDataStream &stream, Basket *parent, bool moveFiles, bool moveNotes, Basket *originalBasket)
+{
+ Q_UINT64 notePointer;
+ Q_UINT64 type;
+ QString fileName;
+ QString fullPath;
+ QDateTime addedDate;
+ QDateTime lastModificationDate;
+
+ Note *firstNote = 0; // TODO: class NoteTreeChunk
+ Note *lastInserted = 0;
+
+ do {
+ stream >> notePointer;
+ if (notePointer == 0)
+ return firstNote;
+ Note *oldNote = (Note*)notePointer;
+
+ Note *note = 0;
+ Q_UINT64 groupWidth;
+ stream >> type >> groupWidth;
+ if (type == NoteType::Group) {
+ note = new Note(parent);
+ note->setGroupWidth(groupWidth);
+ Q_UINT64 isFolded;
+ stream >> isFolded;
+ if (isFolded)
+ note->toggleFolded(/*animate=*/false);
+ if (moveNotes) {
+ note->setX(oldNote->x()); // We don't move groups but re-create them (every childs can to not be selected)
+ note->setY(oldNote->y()); // We just set the position of the copied group so the animation seems as if the group is the same as (or a copy of) the old.
+ note->setHeight(oldNote->height()); // Idem: the only use of Note::setHeight()
+ }
+ Note* childs = decodeHierarchy(stream, parent, moveFiles, moveNotes, originalBasket);
+ if (childs) {
+ for (Note *n = childs; n; n = n->next())
+ n->setParentNote(note);
+ note->setFirstChild(childs);
+ }
+ } else {
+ stream >> fileName >> fullPath >> addedDate >> lastModificationDate;
+ if (moveNotes) {
+ originalBasket->unplugNote(oldNote);
+ note = oldNote;
+ if (note->basket() != parent) {
+ QString newFileName = NoteFactory::createFileForNewNote(parent, "", fileName);
+ note->content()->setFileName(newFileName);
+ KIO::FileCopyJob *copyJob = KIO::file_move(KURL(fullPath), KURL(parent->fullPath() + newFileName),
+ /*perms=*/-1, /*override=*/true, /*resume=*/false, /*showProgressInfo=*/false);
+ parent->connect( copyJob, SIGNAL(result(KIO::Job *)),
+ parent, SLOT(slotCopyingDone2(KIO::Job *)) );
+ }
+ note->setGroupWidth(groupWidth);
+ note->setParentNote(0);
+ note->setPrev(0);
+ note->setNext(0);
+ note->setParentBasket(parent);
+ NoteFactory::consumeContent(stream, (NoteType::Id)type);
+ } else if ( (note = NoteFactory::decodeContent(stream, (NoteType::Id)type, parent)) ) {
+ note->setGroupWidth(groupWidth);
+ note->setAddedDate(addedDate);
+ note->setLastModificationDate(lastModificationDate);
+ } else if (!fileName.isEmpty()) {
+ // Here we are CREATING a new EMPTY file, so the name is RESERVED
+ // (while dropping several files at once a filename cannot be used by two of them).
+ // Later on, file_copy/file_move will copy/move the file to the new location.
+ QString newFileName = NoteFactory::createFileForNewNote(parent, "", fileName);
+ note = NoteFactory::loadFile(newFileName, (NoteType::Id)type, parent);
+ KIO::FileCopyJob *copyJob;
+ if (moveFiles)
+ copyJob = KIO::file_move(KURL(fullPath), KURL(parent->fullPath() + newFileName),
+ /*perms=*/-1, /*override=*/true, /*resume=*/false, /*showProgressInfo=*/false);
+ else
+ copyJob = KIO::file_copy(KURL(fullPath), KURL(parent->fullPath() + newFileName),
+ /*perms=*/-1, /*override=*/true, /*resume=*/false, /*showProgressInfo=*/false);
+ parent->connect( copyJob, SIGNAL(result(KIO::Job *)),
+ parent, SLOT(slotCopyingDone2(KIO::Job *)) );
+ note->setGroupWidth(groupWidth);
+ note->setAddedDate(addedDate);
+ note->setLastModificationDate(lastModificationDate);
+ }
+ }
+ // Retreive the states (tags) and assign them to the note:
+ if (note && note->content()) {
+ Q_UINT64 statePointer;
+ do {
+ stream >> statePointer;
+ if (statePointer)
+ note->addState((State*)statePointer);
+ } while (statePointer);
+ }
+ // Now that we have created the note, insert it:
+ if (note) {
+ if (!firstNote)
+ firstNote = note;
+ else {
+ lastInserted->setNext(note);
+ note->setPrev(lastInserted);
+ }
+ lastInserted = note;
+ }
+ } while (true);
+
+ // We've done: return!
+ return firstNote;
+}
+
+/** ExtendedTextDrag */
+
+bool ExtendedTextDrag::decode(const QMimeSource *e, QString &str)
+{
+ QCString subtype("plain");
+ return decode(e, str, subtype);
+}
+
+bool ExtendedTextDrag::decode(const QMimeSource *e, QString &str, QCString &subtype)
+{
+ // Get the string:
+ bool ok = QTextDrag::decode(e, str, subtype);
+
+ // Test if it was a UTF-16 string (from eg. Mozilla):
+ if (str.length() >= 2) {
+ if ((str[0] == 0xFF && str[1] == 0xFE) || (str[0] == 0xFE && str[1] == 0xFF)) {
+ QByteArray utf16 = e->encodedData(QString("text/" + subtype).local8Bit());
+ str = QTextCodec::codecForName("utf16")->toUnicode(utf16);
+ return true;
+ }
+ }
+
+ // Test if it was empty (sometimes, from GNOME or Mozilla)
+ if (str.length() == 0 && subtype == "plain") {
+ if (e->provides("UTF8_STRING")) {
+ QByteArray utf8 = e->encodedData("UTF8_STRING");
+ str = QTextCodec::codecForName("utf8")->toUnicode(utf8);
+ return true;
+ }
+ if (e->provides("text/unicode")) { // FIXME: It's UTF-16 without order bytes!!!
+ QByteArray utf16 = e->encodedData("text/unicode");
+ str = QTextCodec::codecForName("utf16")->toUnicode(utf16);
+ return true;
+ }
+ if (e->provides("TEXT")) { // local encoding
+ QByteArray text = e->encodedData("TEXT");
+ str = QString(text);
+ return true;
+ }
+ if (e->provides("COMPOUND_TEXT")) { // local encoding
+ QByteArray text = e->encodedData("COMPOUND_TEXT");
+ str = QString(text);
+ return true;
+ }
+ }
+ return ok;
+}
+
+#include "notedrag.moc"