void NoteDrag::serializeLinks(NoteSelection *noteList, K3MultipleDrag *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 ) K3URLDrag *urlsDrag = new K3URLDrag(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 K3URLDrag2 *urlsDrag = new K3URLDrag2(urls); QByteArray byteArray = urlsDrag->encodedData2("text/uri-list"); Q3StoredDrag *uriListDrag = new Q3StoredDrag("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 (int 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, QIODevice::WriteOnly); stream.setEncoding(QTextStream::RawUnicode); // It's UTF16 (aka UCS2), but with the first two order bytes stream << xMozUrl; Q3StoredDrag *xMozUrlDrag = new Q3StoredDrag("text/x-moz-url"); xMozUrlDrag->setEncodedData(baMozUrl); multipleDrag->addDragObject(xMozUrlDrag); if (cutting) { QByteArray arrayCut(2); Q3StoredDrag *storedDragCut = new Q3StoredDrag("application/x-kde-cutselection"); arrayCut[0] = '1'; arrayCut[1] = 0; storedDragCut->setEncodedData(arrayCut); multipleDrag->addDragObject(storedDragCut); } } }
void NoteDrag::serializeText(NoteSelection *noteList, K3MultipleDrag *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 Q3TextDrag(textEquivalent) ); }
QList<Note*> NoteSelection::parentGroups() { QList<Note*> groups; // For each note: for (NoteSelection *node = firstStacked(); node; node = node->nextStacked()) // For each parent groups of the note: for (Note * note = node->note->parentNote(); note; note = note->parentNote()) // Add it (if it was not already in the list): if (!note->isColumn() && !groups.contains(note)) groups.append(note); return groups; }
Q3DragObject* NoteDrag::dragObject(NoteSelection *noteList, bool cutting, QWidget *source) { if (noteList->count() <= 0) return 0; // The MimeSource: K3MultipleDrag *multipleDrag = new K3MultipleDrag(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(QIODevice::WriteOnly)) { QDataStream stream(&buffer); // First append a pointer to the basket: stream << (quint64)(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 << (quint64)(node->note); Q3ValueList<Note*> groups = noteList->parentGroups(); for (Q3ValueList<Note*>::iterator it = groups.begin(); it != groups.end(); ++it) stream << (quint64)(*it); stream << (quint64)0; // And finally the notes themselves: serializeNotes(noteList, stream, cutting); // Append the object: buffer.close(); Q3StoredDrag *dragObject = new Q3StoredDrag(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::serializeHtml(NoteSelection *noteList, K3MultipleDrag *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: Q3TextDrag *htmlDrag = new Q3TextDrag(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(); Q3StoredDrag *richTextDrag = new Q3StoredDrag("application/x-qrichtext"); richTextDrag->setEncodedData(byteArray); multipleDrag->addDragObject(richTextDrag); } }
void NoteDrag::serializeImage(NoteSelection *noteList, K3MultipleDrag *multipleDrag) { Q3ValueList<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 (Q3ValueList<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 (Q3ValueList<QPixmap>::iterator it = pixmaps.begin(); it != pixmaps.end(); ++it) { painter.drawPixmap(0, height, *it); height += (*it).height(); } } Q3ImageDrag *imageDrag = new Q3ImageDrag(pixmapEquivalent.convertToImage()); multipleDrag->addDragObject(imageDrag); } }
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); Q3ValueList<QPixmap> pixmaps; Q3ValueList<QColor> backgrounds; Q3ValueList<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; Q3ValueList<QPixmap>::iterator it; Q3ValueList<QColor>::iterator it2; Q3ValueList<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(); }