Skip to content

Commit 0d2df80

Browse files
committed
Fix clipboard handling on OSX
Clipboard was wrongly using QClipboard::Selection for storage/retrieval when this is not available on OSX Also improve docs
1 parent 28d725c commit 0d2df80

File tree

4 files changed

+37
-70
lines changed

4 files changed

+37
-70
lines changed

src/app/qgisapp.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9840,9 +9840,9 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
98409840
mActionRotateLabel->setEnabled( enableRotate );
98419841
mActionChangeLabelProperties->setEnabled( enableChange );
98429842

9843-
mMenuPasteAs->setEnabled( clipboard() && !clipboard()->empty() );
9844-
mActionPasteAsNewVector->setEnabled( clipboard() && !clipboard()->empty() );
9845-
mActionPasteAsNewMemoryVector->setEnabled( clipboard() && !clipboard()->empty() );
9843+
mMenuPasteAs->setEnabled( clipboard() && !clipboard()->isEmpty() );
9844+
mActionPasteAsNewVector->setEnabled( clipboard() && !clipboard()->isEmpty() );
9845+
mActionPasteAsNewMemoryVector->setEnabled( clipboard() && !clipboard()->isEmpty() );
98469846

98479847
updateLayerModifiedActions();
98489848

@@ -9990,7 +9990,7 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer* layer )
99909990
updateUndoActions();
99919991
}
99929992

9993-
mActionPasteFeatures->setEnabled( isEditable && canAddFeatures && !clipboard()->empty() );
9993+
mActionPasteFeatures->setEnabled( isEditable && canAddFeatures && !clipboard()->isEmpty() );
99949994

99959995
mActionAddFeature->setEnabled( isEditable && canAddFeatures );
99969996
mActionCircularStringCurvePoint->setEnabled( isEditable && ( canAddFeatures || canChangeGeometry ) && vlayer->geometryType() != QGis::Point );

src/app/qgsclipboard.cpp

Lines changed: 21 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void QgsClipboard::setSystemClipboard()
137137
// docs). With a Linux X server, ::Clipboard was required.
138138
// The simple solution was to put the text into both clipboards.
139139

140-
#ifndef Q_OS_WIN
140+
#ifdef Q_OS_LINUX
141141
cb->setText( textCopy, QClipboard::Selection );
142142
#endif
143143
cb->setText( textCopy, QClipboard::Clipboard );
@@ -180,7 +180,7 @@ QgsFields QgsClipboard::retrieveFields() const
180180
{
181181
QClipboard *cb = QApplication::clipboard();
182182

183-
#ifndef Q_OS_WIN
183+
#ifdef Q_OS_LINUX
184184
QString string = cb->text( QClipboard::Selection );
185185
#else
186186
QString string = cb->text( QClipboard::Clipboard );
@@ -189,29 +189,21 @@ QgsFields QgsClipboard::retrieveFields() const
189189
return QgsOgrUtils::stringToFields( string, QTextCodec::codecForName( "System" ) );
190190
}
191191

192-
QgsFeatureList QgsClipboard::copyOf( const QgsFields &fields )
192+
QgsFeatureList QgsClipboard::copyOf( const QgsFields &fields ) const
193193
{
194194
QgsDebugMsg( "returning clipboard." );
195195
if ( !mUseSystemClipboard )
196196
return mFeatureClipboard;
197197

198198
QClipboard *cb = QApplication::clipboard();
199199

200-
#ifndef Q_OS_WIN
200+
#ifdef Q_OS_LINUX
201201
QString text = cb->text( QClipboard::Selection );
202202
#else
203203
QString text = cb->text( QClipboard::Clipboard );
204204
#endif
205205

206-
QgsFeatureList features = stringToFeatureList( text, fields );
207-
208-
if ( features.isEmpty() )
209-
return mFeatureClipboard;
210-
211-
if ( !fields.isEmpty() )
212-
mFeatureFields = fields;
213-
214-
return features;
206+
return stringToFeatureList( text, fields );
215207
}
216208

217209
void QgsClipboard::clear()
@@ -222,7 +214,7 @@ void QgsClipboard::clear()
222214
emit changed();
223215
}
224216

225-
void QgsClipboard::insert( QgsFeature& feature )
217+
void QgsClipboard::insert( const QgsFeature& feature )
226218
{
227219
mFeatureClipboard.push_back( feature );
228220

@@ -231,18 +223,18 @@ void QgsClipboard::insert( QgsFeature& feature )
231223
emit changed();
232224
}
233225

234-
bool QgsClipboard::empty()
226+
bool QgsClipboard::isEmpty() const
235227
{
236228
QClipboard *cb = QApplication::clipboard();
237-
#ifndef Q_OS_WIN
229+
#ifdef Q_OS_LINUX
238230
QString text = cb->text( QClipboard::Selection );
239231
#else
240232
QString text = cb->text( QClipboard::Clipboard );
241233
#endif
242234
return text.isEmpty() && mFeatureClipboard.empty();
243235
}
244236

245-
QgsFeatureList QgsClipboard::transformedCopyOf( const QgsCoordinateReferenceSystem& destCRS, const QgsFields &fields )
237+
QgsFeatureList QgsClipboard::transformedCopyOf( const QgsCoordinateReferenceSystem& destCRS, const QgsFields &fields ) const
246238
{
247239
QgsFeatureList featureList = copyOf( fields );
248240
QgsCoordinateTransform ct( crs(), destCRS );
@@ -256,47 +248,41 @@ QgsFeatureList QgsClipboard::transformedCopyOf( const QgsCoordinateReferenceSyst
256248
return featureList;
257249
}
258250

259-
QgsCoordinateReferenceSystem QgsClipboard::crs()
251+
QgsCoordinateReferenceSystem QgsClipboard::crs() const
260252
{
261253
return mCRS;
262254
}
263255

264-
void QgsClipboard::setData( const QString& mimeType, const QByteArray& data, const QString* text )
256+
void QgsClipboard::setData( const QString& mimeType, const QByteArray& data, const QString& text )
265257
{
258+
mUseSystemClipboard = true;
266259
QMimeData *mdata = new QMimeData();
267260
mdata->setData( mimeType, data );
268-
if ( text )
261+
if ( !text.isEmpty() )
269262
{
270-
mdata->setText( *text );
263+
mdata->setText( text );
271264
}
272265
// Transfers ownership to the clipboard object
273-
#ifndef Q_OS_WIN
266+
#ifdef Q_OS_LINUX
274267
QApplication::clipboard()->setMimeData( mdata, QClipboard::Selection );
275268
#endif
276269
QApplication::clipboard()->setMimeData( mdata, QClipboard::Clipboard );
277270
}
278271

279-
void QgsClipboard::setData( const QString& mimeType, const QByteArray& data, const QString& text )
280-
{
281-
setData( mimeType, data, &text );
282-
}
283-
284-
void QgsClipboard::setData( const QString& mimeType, const QByteArray& data )
285-
{
286-
setData( mimeType, data, nullptr );
287-
}
288-
289272
void QgsClipboard::setText( const QString& text )
290273
{
291-
setData( "text/plain", text.toLocal8Bit(), nullptr );
274+
#ifdef Q_OS_LINUX
275+
QApplication::clipboard()->setText( text, QClipboard::Selection );
276+
#endif
277+
QApplication::clipboard()->setText( text, QClipboard::Clipboard );
292278
}
293279

294-
bool QgsClipboard::hasFormat( const QString& mimeType )
280+
bool QgsClipboard::hasFormat( const QString& mimeType ) const
295281
{
296282
return QApplication::clipboard()->mimeData()->hasFormat( mimeType );
297283
}
298284

299-
QByteArray QgsClipboard::data( const QString& mimeType )
285+
QByteArray QgsClipboard::data( const QString& mimeType ) const
300286
{
301287
return QApplication::clipboard()->mimeData()->data( mimeType );
302288
}

src/app/qgsclipboard.h

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
As this class matures it should also be able to accept CSV repesentations
4141
of features in and out of the system clipboard (QClipboard).
4242
43-
TODO: Make it work
4443
*/
4544

4645
class QgsVectorLayer;
@@ -63,8 +62,8 @@ class APP_EXPORT QgsClipboard : public QObject
6362
virtual ~QgsClipboard();
6463

6564
/**
66-
* Place a copy of features on the internal clipboard,
67-
* destroying the previous contents.
65+
* Place a copy of the selected features from the specified layer on
66+
* the internal clipboard, destroying the previous contents.
6867
*/
6968
void replaceWithCopyOf( QgsVectorLayer *src );
7069

@@ -75,11 +74,9 @@ class APP_EXPORT QgsClipboard : public QObject
7574
void replaceWithCopyOf( QgsFeatureStore & featureStore );
7675

7776
/**
78-
* Returns a copy of features on the internal clipboard,
79-
* the caller assumes responsibility for destroying the contents
80-
* when it's done with it.
77+
* Returns a copy of features on the internal clipboard.
8178
*/
82-
QgsFeatureList copyOf( const QgsFields &fields = QgsFields() );
79+
QgsFeatureList copyOf( const QgsFields &fields = QgsFields() ) const;
8380

8481
/**
8582
* Clears the internal clipboard.
@@ -89,40 +86,28 @@ class APP_EXPORT QgsClipboard : public QObject
8986
/**
9087
* Inserts a copy of the feature on the internal clipboard.
9188
*/
92-
void insert( QgsFeature& feature );
89+
void insert( const QgsFeature& feature );
9390

9491
/**
9592
* Returns true if the internal clipboard is empty, else false.
9693
*/
97-
bool empty();
94+
bool isEmpty() const;
9895

9996
/**
10097
* Returns a copy of features on the internal clipboard, transformed
10198
* from the clipboard CRS to the destCRS.
102-
* The caller assumes responsibility for destroying the contents
103-
* when it's done with it.
10499
*/
105-
QgsFeatureList transformedCopyOf( const QgsCoordinateReferenceSystem& destCRS, const QgsFields &fields = QgsFields() );
100+
QgsFeatureList transformedCopyOf( const QgsCoordinateReferenceSystem& destCRS, const QgsFields &fields = QgsFields() ) const;
106101

107102
/**
108103
* Get the clipboard CRS
109104
*/
110-
QgsCoordinateReferenceSystem crs();
105+
QgsCoordinateReferenceSystem crs() const;
111106

112107
/**
113108
* Stores a MimeData together with a text into the system clipboard
114109
*/
115-
void setData( const QString& mimeType, const QByteArray& data, const QString* text = nullptr );
116-
117-
/**
118-
* Stores a MimeData together with a text into the system clipboard
119-
*/
120-
void setData( const QString& mimeType, const QByteArray& data, const QString& text );
121-
122-
/**
123-
* Stores a MimeData into the system clipboard
124-
*/
125-
void setData( const QString& mimeType, const QByteArray& data );
110+
void setData( const QString& mimeType, const QByteArray& data, const QString& text = QString() );
126111

127112
/**
128113
* Stores a text into the system clipboard
@@ -133,18 +118,18 @@ class APP_EXPORT QgsClipboard : public QObject
133118
* Proxy to QMimeData::hasFormat
134119
* Tests whether the system clipboard contains data of a given MIME type
135120
*/
136-
bool hasFormat( const QString& mimeType );
121+
bool hasFormat( const QString& mimeType ) const;
137122

138123
/**
139124
* Retrieve data from the system clipboard.
140125
* No copy is involved, since the return QByteArray is implicitly shared
141126
*/
142-
QByteArray data( const QString& mimeType );
127+
QByteArray data( const QString& mimeType ) const;
143128

144129
/**
145130
* Source fields
146131
*/
147-
QgsFields fields() { return !mUseSystemClipboard ? mFeatureFields : retrieveFields(); }
132+
QgsFields fields() const { return !mUseSystemClipboard ? mFeatureFields : retrieveFields(); }
148133

149134
private slots:
150135

tests/src/app/testqgisappclipboard.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ void TestQgisAppClipboard::copyPaste()
114114

115115
void TestQgisAppClipboard::pasteWkt()
116116
{
117-
mQgisApp->clipboard()->clear();
118117
mQgisApp->clipboard()->setText( "POINT (125 10)\nPOINT (111 30)" );
119118

120119
QgsFeatureList features = mQgisApp->clipboard()->copyOf();
@@ -133,7 +132,6 @@ void TestQgisAppClipboard::pasteWkt()
133132

134133
void TestQgisAppClipboard::pasteGeoJson()
135134
{
136-
mQgisApp->clipboard()->clear();
137135
QgsFields fields;
138136
fields.append( QgsField( "name", QVariant::String ) );
139137
mQgisApp->clipboard()->setText( "{\n\"type\": \"Feature\",\"geometry\": {\"type\": \"Point\",\"coordinates\": [125, 10]},\"properties\": {\"name\": \"Dinagat Islands\"}}" );
@@ -150,8 +148,6 @@ void TestQgisAppClipboard::pasteGeoJson()
150148

151149
void TestQgisAppClipboard::retrieveFields()
152150
{
153-
mQgisApp->clipboard()->clear();
154-
155151
//empty string
156152
mQgisApp->clipboard()->setText( "" );
157153

0 commit comments

Comments
 (0)