]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiClipboard.cpp
Fix slowness issue with Clipboard. Cache the Clipboard status when the data is changed.
[lyx.git] / src / frontends / qt4 / GuiClipboard.cpp
1 // -*- C++ -*-
2 /**
3  * \file qt4/GuiClipboard.cpp
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author John Levon
8  * \author Abdelrazak Younes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiClipboard.h"
16 #include "qt_helpers.h"
17
18 #include "debug.h"
19
20 #include <QApplication>
21 #include <QClipboard>
22 #include <QMimeData>
23 #include <QString>
24
25 #include "support/lstrings.h"
26
27 using lyx::support::internalLineEnding;
28 using lyx::support::externalLineEnding;
29
30 using std::endl;
31 using std::string;
32
33 static char const * const mime_type = "application/x-lyx";
34
35
36 namespace lyx {
37 namespace frontend {
38
39 GuiClipboard::GuiClipboard()
40 {
41         connect(qApp->clipboard(), SIGNAL(dataChanged()),
42                 this, SLOT(on_dataChanged()));
43         // initialize clipboard status.
44         on_dataChanged()
45 }
46
47
48 string const GuiClipboard::getAsLyX() const
49 {
50         LYXERR(Debug::ACTION) << "GuiClipboard::getAsLyX(): `";
51         // We don't convert encodings here since the encoding of the
52         // clipboard contents is specified in the data itself
53         QMimeData const * source =
54                 qApp->clipboard()->mimeData(QClipboard::Clipboard);
55         if (!source) {
56                 LYXERR(Debug::ACTION) << "' (no QMimeData)" << endl;
57                 return string();
58         }
59         if (source->hasFormat(mime_type)) {
60                 // data from ourself or some other LyX instance
61                 QByteArray const ar = source->data(mime_type);
62                 string const s(ar.data(), ar.count());
63                 LYXERR(Debug::ACTION) << s << "'" << endl;
64                 return s;
65         }
66         LYXERR(Debug::ACTION) << "'" << endl;
67         return string();
68 }
69
70
71 docstring const GuiClipboard::getAsText() const
72 {
73         // text data from other applications
74         QString const str = qApp->clipboard()->text(QClipboard::Clipboard)
75                                 .normalized(QString::NormalizationForm_C);
76         LYXERR(Debug::ACTION) << "GuiClipboard::getAsText(): `"
77                               << fromqstr(str) << "'" << endl;
78         if (str.isNull())
79                 return docstring();
80
81         return internalLineEnding(qstring_to_ucs4(str));
82 }
83
84
85 void GuiClipboard::put(string const & lyx, docstring const & text)
86 {
87         LYXERR(Debug::ACTION) << "GuiClipboard::put(`" << lyx << "' `"
88                               << to_utf8(text) << "')" << endl;
89         // We don't convert the encoding of lyx since the encoding of the
90         // clipboard contents is specified in the data itself
91         QMimeData * data = new QMimeData;
92         if (!lyx.empty()) {
93                 QByteArray const qlyx(lyx.c_str(), lyx.size());
94                 data->setData(mime_type, qlyx);
95         }
96         // Don't test for text.empty() since we want to be able to clear the
97         // clipboard.
98         QString const qtext = toqstr(text);
99         data->setText(qtext);
100         qApp->clipboard()->setMimeData(data, QClipboard::Clipboard);
101 }
102
103
104 bool GuiClipboard::hasLyXContents() const
105 {
106         QMimeData const * const source =
107                 qApp->clipboard()->mimeData(QClipboard::Clipboard);
108         return source && source->hasFormat(mime_type);
109 }
110
111
112 bool GuiClipboard::isInternal() const
113 {
114         // ownsClipboard() is also true for stuff coming from dialogs, e.g.
115         // the preamble dialog
116         // FIXME: This does only work on X11, since ownsClipboard() is
117         // hardwired to return false on Windows and OS X.
118         return qApp->clipboard()->ownsClipboard() && hasLyXContents();
119 }
120
121
122 void GuiClipboard::on_dataChanged()
123 {
124         text_clipboard_empty_ = qApp->clipboard()->
125                 text(QClipboard::Clipboard).isEmpty();
126
127         has_lyx_contents_ = hasLyXContents();
128 }
129
130
131 bool GuiClipboard::empty() const
132 {
133         // We need to check both the plaintext and the LyX version of the
134         // clipboard. The plaintext version is empty if the LyX version
135         // contains only one inset, and the LyX version is empty if the
136         // clipboard does not come from LyX.
137         if (!text_clipboard_empty_)
138                 return false;
139         return !has_lyx_contents_;
140 }
141
142 } // namespace frontend
143 } // namespace lyx
144
145 #include "GuiClipboard_moc.cpp"