KiCad PCB EDA Suite
Loading...
Searching...
No Matches
clipboard.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include "clipboard.h"
25
26#include <wx/clipbrd.h>
27#include <wx/dataobj.h>
28#include <wx/image.h>
29#include <wx/log.h>
30#include <wx/mstream.h>
31#include <wx/string.h>
32#include <wx/sstream.h>
33
34#include <sstream>
35
36#include <io/csv.h>
37
38
39bool SaveClipboard( const std::string& aTextUTF8 )
40{
41 wxLogNull doNotLog; // disable logging of failed clipboard actions
42
43 if( wxTheClipboard->Open() )
44 {
45 // Store the UTF8 string as Unicode string in clipboard:
46 wxTheClipboard->SetData(
47 new wxTextDataObject( wxString( aTextUTF8.c_str(), wxConvUTF8 ) ) );
48
49 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
50 wxTheClipboard->Close();
51
52 return true;
53 }
54
55 return false;
56}
57
58
59bool SaveClipboard( const std::string& aTextUTF8, const std::vector<CLIPBOARD_MIME_DATA>& aMimeData )
60{
61 if( aMimeData.empty() )
62 return SaveClipboard( aTextUTF8 );
63
64 wxLogNull doNotLog; // disable logging of failed clipboard actions
65
66 if( wxTheClipboard->Open() )
67 {
68 wxDataObjectComposite* data = new wxDataObjectComposite();
69 data->Add( new wxTextDataObject( wxString( aTextUTF8.c_str(), wxConvUTF8 ) ), true );
70
71 for( const CLIPBOARD_MIME_DATA& entry : aMimeData )
72 {
73 // Skip entries with no data
74 if( entry.m_data.GetDataLen() == 0 )
75 continue;
76
77 // For PNG data, add as wxBitmapDataObject for compatibility with image
78 // applications like GIMP that expect standard bitmap clipboard format.
79 // We use wxBitmapDataObject instead of custom format because it's more
80 // widely supported and avoids clipboard format query issues.
81 if( entry.m_mimeType == wxS( "image/png" ) )
82 {
83 wxMemoryInputStream stream( entry.m_data.GetData(), entry.m_data.GetDataLen() );
84 wxImage image;
85
86 if( image.LoadFile( stream, wxBITMAP_TYPE_PNG ) && image.IsOk() )
87 {
88 data->Add( new wxBitmapDataObject( wxBitmap( image ) ) );
89 }
90
91 // Don't also add as custom format - wxBitmapDataObject is sufficient
92 // for image apps, and adding both can cause clipboard query issues
93 continue;
94 }
95
96 // Add custom format data - note that on GTK, custom MIME types may not work
97 // with all applications (they often become wxDF_PRIVATE internally), but they
98 // work for KiCad-to-KiCad transfers.
99 // We allocate and set data in a way that ensures the object is fully initialized.
100 wxDataFormat format( entry.m_mimeType );
101 wxCustomDataObject* custom = new wxCustomDataObject( format );
102
103 // Allocate buffer first, then copy data - this ensures proper initialization
104 custom->Alloc( entry.m_data.GetDataLen() );
105 custom->SetData( entry.m_data.GetDataLen(), entry.m_data.GetData() );
106 data->Add( custom );
107 }
108
109 wxTheClipboard->SetData( data );
110 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
111 wxTheClipboard->Close();
112
113 return true;
114 }
115
116 return false;
117}
118
119
120std::string GetClipboardUTF8()
121{
122 std::string result;
123
124 wxLogNull doNotLog; // disable logging of failed clipboard actions
125
126 if( wxTheClipboard->Open() )
127 {
128 if( wxTheClipboard->IsSupported( wxDataFormat( wxS( "application/kicad" ) ) ) )
129 {
130 wxCustomDataObject data( wxDataFormat( wxS( "application/kicad" ) ) );
131
132 if( wxTheClipboard->GetData( data ) )
133 {
134 result.assign( static_cast<const char*>( data.GetData() ), data.GetSize() );
135 wxTheClipboard->Close();
136 return result;
137 }
138 }
139
140 if( wxTheClipboard->IsSupported( wxDF_TEXT )
141 || wxTheClipboard->IsSupported( wxDF_UNICODETEXT ) )
142 {
143 wxTextDataObject data;
144 wxTheClipboard->GetData( data );
145
146 // The clipboard is expected containing a Unicode string, so return it
147 // as UTF8 string
148 result = data.GetText().utf8_str();
149 }
150
151 wxTheClipboard->Close();
152 }
153
154 return result;
155}
156
157
158std::unique_ptr<wxImage> GetImageFromClipboard()
159{
160 std::unique_ptr<wxImage> image;
161 wxLogNull doNotLog; // disable logging of failed clipboard actions
162
163 // First try for an image
164 if( wxTheClipboard->Open() )
165 {
166 if( wxTheClipboard->IsSupported( wxDF_BITMAP ) )
167 {
168 wxBitmapDataObject data;
169 if( wxTheClipboard->GetData( data ) )
170 {
171 image = std::make_unique<wxImage>( data.GetBitmap().ConvertToImage() );
172 }
173 }
174 else if( wxTheClipboard->IsSupported( wxDF_FILENAME ) )
175 {
176 wxFileDataObject data;
177 if( wxTheClipboard->GetData( data ) && data.GetFilenames().size() == 1 )
178 {
179 image = std::make_unique<wxImage>( data.GetFilenames()[0] );
180
181 if( !image->IsOk() )
182 image.reset();
183 }
184 }
185
186 wxTheClipboard->Close();
187 }
188
189 return image;
190}
191
192
193bool SaveTabularDataToClipboard( const std::vector<std::vector<wxString>>& aData )
194{
195 wxLogNull doNotLog; // disable logging of failed clipboard actions
196
197 if( wxTheClipboard->Open() )
198 {
199 wxDataObjectComposite* data = new wxDataObjectComposite();
200
201 // Set plain text CSV
202 {
203 wxStringOutputStream os;
204 CSV_WRITER writer( os );
205 writer.WriteLines( aData );
206
207 data->Add( new wxTextDataObject( os.GetString() ), true );
208 }
209
210 // At this point, it would be great if we could add some format that spreadsheet
211 // programs can understand without asking the user for options: perhaps SYLK or DIF.
212 // But it doesn't seem like WX allows to put arbitrary MIME types on the clipboard,
213 // even with wxCustomDataObject( wxDataFormat( "mime/type" ) ), which just ends up as
214 // wxDF_PRIVATE, and wxDF_SYLK/DIF aren't mapped on GTK.
215
216 wxTheClipboard->SetData( data );
217 wxTheClipboard->Flush(); // Allow data to be available after closing KiCad
218 wxTheClipboard->Close();
219
220 return true;
221 }
222
223 return false;
224}
225
226
227bool GetTabularDataFromClipboard( std::vector<std::vector<wxString>>& aData )
228{
229 // Again, it would be ideal if we could detect a spreadsheet mimetype here,
230 // but WX doesn't seem to do that on Linux, at least.
231
232 bool ok = false;
233
234 // First try for text data
235 if( wxTheClipboard->Open() )
236 {
237 if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
238 {
239 wxTextDataObject data;
240 if( wxTheClipboard->GetData( data ) )
241 {
242 ok = AutoDecodeCSV( data.GetText(), aData );
243 }
244 }
245
246 // We could also handle .csv wxDF_FILENAMEs here
247
248 wxTheClipboard->Close();
249 }
250
251 return ok;
252}
void WriteLines(const std::vector< std::vector< wxString > > &aRows)
Write a vector of rows to the stream.
Definition csv.cpp:18
bool SaveTabularDataToClipboard(const std::vector< std::vector< wxString > > &aData)
Store tabular data to the system clipboard.
bool SaveClipboard(const std::string &aTextUTF8)
Store information to the system clipboard.
Definition clipboard.cpp:39
std::string GetClipboardUTF8()
Return the information currently stored in the system clipboard.
std::unique_ptr< wxImage > GetImageFromClipboard()
Get image data from the clipboard, if there is any.
bool GetTabularDataFromClipboard(std::vector< std::vector< wxString > > &aData)
Attempt to get tabular data from the clipboard.
bool AutoDecodeCSV(const wxString &aInput, std::vector< std::vector< wxString > > &aData)
Try to guess the format of a T/CSV file and decode it into aData.
Definition csv.cpp:66
wxString result
Test unit parsing edge cases and error handling.