+FileName GuiClipboard::getPastedGraphicsFileName(Cursor const & cur,
+ Clipboard::GraphicsType & type) const
+{
+ // create file dialog filter according to the existing types in the clipboard
+ vector<Clipboard::GraphicsType> types;
+ if (hasGraphicsContents(Clipboard::EmfGraphicsType))
+ types.push_back(Clipboard::EmfGraphicsType);
+ if (hasGraphicsContents(Clipboard::WmfGraphicsType))
+ types.push_back(Clipboard::WmfGraphicsType);
+ if (hasGraphicsContents(Clipboard::LinkBackGraphicsType))
+ types.push_back(Clipboard::LinkBackGraphicsType);
+ if (hasGraphicsContents(Clipboard::PdfGraphicsType))
+ types.push_back(Clipboard::PdfGraphicsType);
+ if (hasGraphicsContents(Clipboard::PngGraphicsType))
+ types.push_back(Clipboard::PngGraphicsType);
+ if (hasGraphicsContents(Clipboard::JpegGraphicsType))
+ types.push_back(Clipboard::JpegGraphicsType);
+
+ LASSERT(!types.empty(), return FileName());
+
+ // select prefered type if AnyGraphicsType was passed
+ if (type == Clipboard::AnyGraphicsType)
+ type = types.front();
+
+ // which extension?
+ map<Clipboard::GraphicsType, string> extensions;
+ map<Clipboard::GraphicsType, docstring> typeNames;
+
+ extensions[Clipboard::EmfGraphicsType] = "emf";
+ extensions[Clipboard::WmfGraphicsType] = "wmf";
+ extensions[Clipboard::LinkBackGraphicsType] = "linkback";
+ extensions[Clipboard::PdfGraphicsType] = "pdf";
+ extensions[Clipboard::PngGraphicsType] = "png";
+ extensions[Clipboard::JpegGraphicsType] = "jpeg";
+
+ typeNames[Clipboard::EmfGraphicsType] = _("Enhanced Metafile");
+ typeNames[Clipboard::WmfGraphicsType] = _("Windows Metafile");
+ typeNames[Clipboard::LinkBackGraphicsType] = _("LinkBack PDF");
+ typeNames[Clipboard::PdfGraphicsType] = _("PDF");
+ typeNames[Clipboard::PngGraphicsType] = _("PNG");
+ typeNames[Clipboard::JpegGraphicsType] = _("JPEG");
+
+ // find unused filename with primary extension
+ string document_path = cur.buffer()->fileName().onlyPath().absFileName();
+ unsigned newfile_number = 0;
+ FileName filename;
+ do {
+ ++newfile_number;
+ filename = FileName(addName(document_path,
+ to_utf8(_("pasted"))
+ + convert<string>(newfile_number) + "."
+ + extensions[type]));
+ } while (filename.isReadableFile());
+
+ while (true) {
+ // create file type filter, putting the prefered on to the front
+ QStringList filter;
+ for (size_t i = 0; i != types.size(); ++i) {
+ docstring s = bformat(_("%1$s Files"), typeNames[types[i]])
+ + " (*." + from_ascii(extensions[types[i]]) + ")";
+ if (types[i] == type)
+ filter.prepend(toqstr(s));
+ else
+ filter.append(toqstr(s));
+ }
+ filter = fileFilters(filter.join(";;"));
+
+ // show save dialog for the graphic
+ FileDialog dlg(qt_("Choose a filename to save the pasted graphic as"));
+ FileDialog::Result result =
+ dlg.save(toqstr(filename.onlyPath().absFileName()), filter,
+ toqstr(filename.onlyFileName()));
+
+ if (result.first == FileDialog::Later)
+ return FileName();
+
+ string newFilename = fromqstr(result.second);
+ if (newFilename.empty()) {
+ cur.bv().message(_("Canceled."));
+ return FileName();
+ }
+ filename.set(newFilename);
+
+ // check the extension (the user could have changed it)
+ if (!suffixIs(ascii_lowercase(filename.absFileName()),
+ "." + extensions[type])) {
+ // the user changed the extension. Check if the type is available
+ size_t i;
+ for (i = 1; i != types.size(); ++i) {
+ if (suffixIs(ascii_lowercase(filename.absFileName()),
+ "." + extensions[types[i]])) {
+ type = types[i];
+ break;
+ }
+ }
+
+ // invalid extension found, or none at all. In the latter
+ // case set the default extensions.
+ if (i == types.size()
+ && filename.onlyFileName().find('.') == string::npos) {
+ filename.changeExtension("." + extensions[type]);
+ }
+ }
+
+ // check whether the file exists and warn the user
+ if (!filename.exists())
+ break;
+ int ret = frontend::Alert::prompt(
+ _("Overwrite external file?"),
+ bformat(_("File %1$s already exists, do you want to overwrite it?"),
+ from_utf8(filename.absFileName())), 1, 1, _("&Overwrite"), _("&Cancel"));
+ if (ret == 0)
+ // overwrite, hence break the dialog loop
+ break;
+
+ // not overwrite, hence show the dialog again (i.e. loop)
+ }
+
+ return filename;
+}
+
+
+FileName GuiClipboard::getAsGraphics(Cursor const & cur, GraphicsType type) const
+{
+ // get the filename from the user
+ FileName filename = getPastedGraphicsFileName(cur, type);
+ if (filename.empty())
+ return FileName();
+
+ // handle image cases first
+ if (type == PngGraphicsType || type == JpegGraphicsType) {
+ // get image from QImage from clipboard
+ QImage image = qApp->clipboard()->image();
+ if (image.isNull()) {
+ LYXERR(Debug::CLIPBOARD, "No image in clipboard");
+ return FileName();
+ }
+
+ // convert into graphics format
+ QByteArray ar;
+ QBuffer buffer(&ar);
+ buffer.open(QIODevice::WriteOnly);
+ if (type == PngGraphicsType)
+ image.save(toqstr(filename.absFileName()), "PNG");
+ else if (type == JpegGraphicsType)
+ image.save(toqstr(filename.absFileName()), "JPEG");
+ else
+ LATTEST(false);
+
+ return filename;
+ }
+
+ // get mime for type
+ QString mime;
+ switch (type) {
+ case PdfGraphicsType: mime = pdfMimeType(); break;
+ case LinkBackGraphicsType: mime = pdfMimeType(); break;
+ case EmfGraphicsType: mime = emfMimeType(); break;
+ case WmfGraphicsType: mime = wmfMimeType(); break;
+ default: LASSERT(false, return FileName());
+ }
+
+ // get data
+ if (!cache_.hasFormat(mime))
+ return FileName();
+ // data from ourself or some other LyX instance
+ QByteArray const ar = cache_.data(mime);
+ LYXERR(Debug::CLIPBOARD, "Getting from clipboard: mime = " << mime.constData()
+ << "length = " << ar.count());
+
+ QFile f(toqstr(filename.absFileName()));
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ LYXERR(Debug::CLIPBOARD, "Error opening file "
+ << filename.absFileName() << " for writing");
+ return FileName();
+ }
+
+ // write the (LinkBack) PDF data
+ f.write(ar);
+ if (type == LinkBackGraphicsType) {
+#ifdef Q_OS_MAC
+ void const * linkBackData;
+ unsigned linkBackLen;
+ getLinkBackData(&linkBackData, &linkBackLen);
+ f.write((char *)linkBackData, linkBackLen);
+ quint32 pdfLen = ar.size();
+ QDataStream ds(&f);
+ ds << pdfLen; // big endian by default
+#else
+ // only non-Mac this should never happen
+ LATTEST(false);
+#endif // Q_OS_MAC
+ }
+
+ f.close();
+ return filename;
+}
+
+
+namespace {
+/**
+ * Tidy up a HTML chunk coming from the clipboard.
+ * This is needed since different applications put different kinds of HTML
+ * on the clipboard:
+ * - With or without the <?xml> tag
+ * - With or without the <!DOCTYPE> tag
+ * - With or without the <html> tag
+ * - With or without the <body> tag
+ * - With or without the <p> tag
+ * Since we are going to write a HTML file for external converters we need
+ * to ensure that it is a well formed HTML file, including all the mentioned tags.
+ */
+QString tidyHtml(QString input)
+{
+ // Misuse QTextDocument to cleanup the HTML.
+ // As a side effect, all visual markup like <tt> is converted to CSS,
+ // which is ignored by gnuhtml2latex.
+ // While this may be seen as a bug by some people it is actually a
+ // good thing, since we do import structure, but ignore all visual
+ // clutter.
+ QTextDocument converter;
+ converter.setHtml(input);
+ return converter.toHtml("utf-8");
+}
+}
+
+
+docstring const GuiClipboard::getAsText(TextType type) const