X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiClipboard.cpp;h=297b828948e45612d0a50456fcfe8ddfe70f4526;hb=8e7d7e42952f0119db1c192386a63d1d9ede3b7f;hp=ec6b916e4506c46e86be8620a63b8c1b98defd0f;hpb=d57b6f315d7c26f878d8a1fb2b72f5ce0b2a0e49;p=lyx.git diff --git a/src/frontends/qt4/GuiClipboard.cpp b/src/frontends/qt4/GuiClipboard.cpp index ec6b916e45..297b828948 100644 --- a/src/frontends/qt4/GuiClipboard.cpp +++ b/src/frontends/qt4/GuiClipboard.cpp @@ -27,6 +27,7 @@ #include "support/filetools.h" #include "support/gettext.h" #include "support/lstrings.h" +#include "support/lyxtime.h" #ifdef Q_WS_MACX #include "support/linkback/LinkBackProxy.h" @@ -46,6 +47,7 @@ #include #include +#include using namespace std; using namespace lyx::support; @@ -55,6 +57,43 @@ namespace lyx { namespace frontend { +static QMimeData const * read_clipboard() +{ + LYXERR(Debug::ACTION, "Getting Clipboard"); + QMimeData const * source = + qApp->clipboard()->mimeData(QClipboard::Clipboard); + if (!source) { + LYXERR0("0 bytes (no QMimeData)"); + return new QMimeData(); + } + // It appears that doing IO between getting a mimeData object + // and using it can cause a crash (maybe Qt used IO + // as an excuse to free() it? Anyway let's not introduce + // any new IO here, so e.g. leave the following line commented. + // lyxerr << "Got Clipboard (" << (long) source << ")\n" ; + return source; +} + + +void CacheMimeData::update() +{ + time_t const start_time = current_time(); + LYXERR(Debug::ACTION, "Creating CacheMimeData object"); + cached_formats_ = read_clipboard()->formats(); + + // Qt times out after 5 seconds if it does not recieve a response. + if (current_time() - start_time > 3) { + LYXERR0("No timely response from clipboard, perhaps process " + << "holding clipboard is frozen?"); + } +} + + +QByteArray CacheMimeData::data(QString const & mimeType) const +{ + return read_clipboard()->data(mimeType); +} + QString const lyxMimeType(){ return "application/x-lyx"; } QString const pdfMimeType(){ return "application/pdf"; } @@ -76,16 +115,9 @@ string const GuiClipboard::getAsLyX() const LYXERR(Debug::ACTION, "GuiClipboard::getAsLyX(): `"); // We don't convert encodings here since the encoding of the // clipboard contents is specified in the data itself - QMimeData const * source = - qApp->clipboard()->mimeData(QClipboard::Clipboard); - if (!source) { - LYXERR(Debug::ACTION, "' (no QMimeData)"); - return string(); - } - - if (source->hasFormat(lyxMimeType())) { + if (cache_.hasFormat(lyxMimeType())) { // data from ourself or some other LyX instance - QByteArray const ar = source->data(lyxMimeType()); + QByteArray const ar = cache_.data(lyxMimeType()); string const s(ar.data(), ar.count()); LYXERR(Debug::ACTION, s << "'"); return s; @@ -138,7 +170,7 @@ FileName GuiClipboard::getPastedGraphicsFileName(Cursor const & cur, typeNames[Clipboard::JpegGraphicsType] = _("JPEG"); // find unused filename with primary extension - string document_path = cur.buffer()->fileName().onlyPath().absFilename(); + string document_path = cur.buffer()->fileName().onlyPath().absFileName(); unsigned newfile_number = 0; FileName filename; do { @@ -165,7 +197,7 @@ FileName GuiClipboard::getPastedGraphicsFileName(Cursor const & cur, // 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, + dlg.save(toqstr(filename.onlyPath().absFileName()), filter, toqstr(filename.onlyFileName())); if (result.first == FileDialog::Later) @@ -179,12 +211,12 @@ FileName GuiClipboard::getPastedGraphicsFileName(Cursor const & cur, filename.set(newFilename); // check the extension (the user could have changed it) - if (!suffixIs(ascii_lowercase(filename.absFilename()), + 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()), + if (suffixIs(ascii_lowercase(filename.absFileName()), "." + extensions[types[i]])) { type = types[i]; break; @@ -205,7 +237,7 @@ FileName GuiClipboard::getPastedGraphicsFileName(Cursor const & cur, 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")); + from_utf8(filename.absFileName())), 1, 1, _("&Overwrite"), _("&Cancel")); if (ret == 0) // overwrite, hence break the dialog loop break; @@ -238,23 +270,15 @@ FileName GuiClipboard::getAsGraphics(Cursor const & cur, GraphicsType type) cons QBuffer buffer(&ar); buffer.open(QIODevice::WriteOnly); if (type == PngGraphicsType) - image.save(toqstr(filename.absFilename()), "PNG"); + image.save(toqstr(filename.absFileName()), "PNG"); else if (type == JpegGraphicsType) - image.save(toqstr(filename.absFilename()), "JPEG"); + image.save(toqstr(filename.absFileName()), "JPEG"); else LASSERT(false, /**/); return filename; } - // get mime data - QMimeData const * source = - qApp->clipboard()->mimeData(QClipboard::Clipboard); - if (!source) { - LYXERR(Debug::ACTION, "0 bytes (no QMimeData)"); - return FileName(); - } - // get mime for type QString mime; switch (type) { @@ -266,17 +290,17 @@ FileName GuiClipboard::getAsGraphics(Cursor const & cur, GraphicsType type) cons } // get data - if (!source->hasFormat(mime)) + if (!cache_.hasFormat(mime)) return FileName(); // data from ourself or some other LyX instance - QByteArray const ar = source->data(mime); + QByteArray const ar = cache_.data(mime); LYXERR(Debug::ACTION, "Getting from clipboard: mime = " << mime.data() << "length = " << ar.count()); - QFile f(toqstr(filename.absFilename())); + QFile f(toqstr(filename.absFileName())); if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { LYXERR(Debug::ACTION, "Error opening file " - << filename.absFilename() << " for writing"); + << filename.absFileName() << " for writing"); return FileName(); } @@ -336,17 +360,13 @@ void GuiClipboard::put(string const & lyx, docstring const & text) bool GuiClipboard::hasLyXContents() const { - QMimeData const * const source = - qApp->clipboard()->mimeData(QClipboard::Clipboard); - return source && source->hasFormat(lyxMimeType()); + return cache_.hasFormat(lyxMimeType()); } bool GuiClipboard::hasTextContents() const { - QMimeData const * const source = - qApp->clipboard()->mimeData(QClipboard::Clipboard); - return source && source->hasText(); + return cache_.hasText(); } @@ -361,12 +381,9 @@ bool GuiClipboard::hasGraphicsContents(Clipboard::GraphicsType type) const || hasGraphicsContents(LinkBackGraphicsType); } - QMimeData const * const source = - qApp->clipboard()->mimeData(QClipboard::Clipboard); - // handle image cases first if (type == PngGraphicsType || type == JpegGraphicsType) - return source->hasImage(); + return cache_.hasImage(); // handle LinkBack for Mac if (type == LinkBackGraphicsType) @@ -377,7 +394,7 @@ bool GuiClipboard::hasGraphicsContents(Clipboard::GraphicsType type) const #endif // Q_WS_MACX // get mime data - QStringList const & formats = source->formats(); + QStringList const & formats = cache_.formats(); LYXERR(Debug::ACTION, "We found " << formats.size() << " formats"); for (int i = 0; i < formats.size(); ++i) LYXERR(Debug::ACTION, "Found format " << formats[i]); @@ -391,7 +408,7 @@ bool GuiClipboard::hasGraphicsContents(Clipboard::GraphicsType type) const default: LASSERT(false, /**/); } - return source && source->hasFormat(mime); + return cache_.hasFormat(mime); } @@ -420,9 +437,14 @@ bool GuiClipboard::hasInternal() const void GuiClipboard::on_dataChanged() { - QMimeData const * const source = - qApp->clipboard()->mimeData(QClipboard::Clipboard); - QStringList l = source->formats(); + //Note: we do not really need to run cache_.update() unless the + //data has been changed *and* the GuiClipboard has been queried. + //However if run cache_.update() the moment a process grabs the + //clipboard, the process holding the clipboard presumably won't + //yet be frozen, and so we won't need to wait 5 seconds for Qt + //to time-out waiting for the clipboard. + cache_.update(); + QStringList l = cache_.formats(); LYXERR(Debug::ACTION, "Qt Clipboard changed. We found the following mime types:"); for (int i = 0; i < l.count(); i++) LYXERR(Debug::ACTION, l.value(i));