The other day I needed to do something that should be very easy, but I ran into some problems. Lots of google searching and I eventually was able to scrounge together enough to make it work, and I’d like to save others the trouble.
One of the feature requests we had recently for Hexels was copy and paste across multiple instances of the application. Hexels always did have copy and paste, but it just stored the data in application memory rather than using the system clipboard, so it couldn’t go across difference instances and it vanished when you quit the app.
I suppose I could have just saved the data to a file in Hexels’ temp directory, and that would have served my purposes. Probably better than using the clipboard, even, since then it wouldn’t overwrite what was already on there. But I wanted to use the system clipboard. Besides, eventually I’d like to also convert the selection to an image for pasting into other apps.
So anyway, Hexels is built on the QT framework, which is pretty awesome and does support clipboard operations. In fact, it’s this simple:
void copyToClipboard(unsigned char* genericData, int size)
{
QByteArray a((char*)genericData, size);
QMimeData* qmd = new QMimeData;
qmd->setData("HEXELS", a);
QApplication::clipboard()->clear();
QApplication::clipboard()->setMimeData(qmd);
}
Easy, right? Except it doesn’t persist when the app exits. So what good is that? It’s probably all most people would need, but it’s sort of like breaking a promise if your clipboard data doesn’t stick around, isn’t it? By the way, I swear I properly indent my code, the formatting is just from WordPress. I’m not sure good with it yet.
So I did what any good programmer does, and I googled it. Something about clipboard ownership and flushing and whatnot. Not many results, though, which is actually the reason I’m writing a blog post about such a mundane topic that I, as you’ll see, solved very inelegantly.
On Windows, it turns out that flushing the clipboard to the system such that it persists upon exit is easy. Just call
OleFlushClipboard(); //needed to retain clipboard between app launches
Then later you can grab the data like this:
unsigned char* getDataFromClipboard(int& size)
{
size = 0;
//grab the clipboard and a pointer to all its data
const QMimeData* data = QApplication::clipboard()->mimeData();
if(!data) return NULL;
//is there HEXELS data here?
QByteArray a = data->data(“HEXELS”);
size = a.size();
if(!a.size()) return NULL;
//the pointer might not be good after we leave the function, so make a copy of the data
//you’ll have to delete it yourself later
unsigned char* newData = new unsigned char[a.size()];
memcpy(newData, a.data(), a.size());
return newData;
}
And that’s it!
Except on Mac. Macs don’t have OleFlushClipboard, and Google couldn’t offer me an alternative. For Mac I had to go a somewhat more format route and use Objective-C. Looking at Apple dev docs, I put together the following:
void copyToClipboard(unsigned char* genericData, int size)
{
//establish clipboard ownership on Mac
NSPasteboard* pb = [NSPasteboard generalPasteboard];
[pb clearContents];
NSData* cpdata = [[NSData alloc] initWithBytes:genericData length:size];
[pb setData:cpdata forType:@”HEXELS”];
}
unsigned char* getDataFromClipboard(int& size)
{
size = 0;
NSPasteboard* pb = [NSPasteboard generalPasteboard];
NSData* cpdata = [pb dataForType:@”HEXELS”];
if(cpdata)
{
size = [cpdata length];
unsigned char* dater = new unsigned char[size];
memcpy(dater, [cpdata bytes], size);
return dater;
}
return NULL;
}
You might be wondering why the getDataFromClipboard function has to be different on Mac. I’m wondering the same thing. For some reason, Hexels data copied straight to the Mac system clipboard wasn’t accessible to Qt.
So there you go, everything you need to use the clipboard on Windows and Mac. I suspect these functions could be modified to put data on the clipboard in multiple formats simultaneously, like pasting Hexels data into Hexels or pasting an image into Photoshop. Is this the “correct” way to do this? I doubt it. But it works for me, on both Mac (OSX 10.9) and Windows 7. It also gets around some issues that Google wasn’t very helpful with, and those things are what matter. Enjoy!