summaryrefslogtreecommitdiff
path: root/qt4_clip.cpp
blob: c489e0bc70ed1127b0caa063e73a7b8e7280dfd6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// Compile: g++ -I/usr/include/qt4 -L/usr/lib/qt4/lib -o qt4_clip qt4_clip.cpp -lQtGui -lQtCore
#include <QtCore/QString>
#include <QtGui/QApplication>
#include <QtGui/QClipboard>
#include <fstream>
#include <iostream>
#include <string>
#include <unistd.h>

// Abstract class to define a generic clipboard accessor.
class CClipboardAccess
{
public:
	explicit CClipboardAccess(const std::string &name) : Name(name) {}
	virtual ~CClipboardAccess() {}
	inline const std::string& GetName() const { return this->Name; }

	virtual void ClearClipboard() const = 0;
	virtual void SetClipboard(const std::string &str) const = 0;
	virtual std::string GetClipboard() const = 0;

private:
	std::string Name;
};

// A class to access the clipboard using the Qt QClipboard.
class CQtClipboardAccess : public CClipboardAccess
{
public:
	explicit CQtClipboardAccess(QApplication &app) : CClipboardAccess("QClipboard"), pApp(&app), pClip(QApplication::clipboard()) {}
	virtual ~CQtClipboardAccess() {}

	virtual void ClearClipboard() const
	{
		this->pApp->processEvents();
		this->pClip->clear(QClipboard::Clipboard);
		if (this->pClip->supportsSelection())
			this->pClip->clear(QClipboard::Selection);
	}

	virtual void SetClipboard(const std::string &str) const
	{
		this->pApp->processEvents();
		this->pClip->setText(str.c_str(), QClipboard::Clipboard);
		if (this->pClip->supportsSelection())
			this->pClip->setText(str.c_str(), QClipboard::Selection);
	}

	virtual std::string GetClipboard() const
	{
		this->pApp->processEvents();
		return this->pClip->text(QClipboard::Clipboard).toStdString();
	}

private:
	QApplication *pApp;
	QClipboard *pClip;
};

// A class to access the clipboard by reading / writing to '/dev/clipboard'.
class CCygwinClipboardAccess : public CClipboardAccess
{
public:
	CCygwinClipboardAccess() : CClipboardAccess("/dev/clipboard") {}
	virtual ~CCygwinClipboardAccess() {}

	virtual void ClearClipboard() const
	{
		this->SetClipboard("");
	}

	virtual void SetClipboard(const std::string &str) const
	{
		std::ofstream out(this->GetName().c_str());
		if (!out)
			std::cerr << "Unable to write to '" << this->GetName() << "'." << std::endl;
		else
			out << str;
	}

	virtual std::string GetClipboard() const
	{
		std::string line;
		std::ifstream in(this->GetName().c_str());
		if (!in)
			std::cerr << "Unable to read '" << this->GetName() << "'." << std::endl;
		else
			std::getline(in, line);
		return line;
	}
};

class CTest : public QApplication
{
public:
	CTest(int argc, char **pargv) : QApplication(argc, pargv) {}
	virtual ~CTest() {}

	void GoTest()
	{
		CQtClipboardAccess qt_clip(*this);
		CCygwinClipboardAccess cygwin_clip;

		// The tests.
		//
		// With 64-bit XWin, test 3 always fails, but for 32-bit XWin the same test passes.
		// This is true, irrespective of whether this code is compiled and run from 32-bit Cygwin or 64-bit Cygwin.
		//
		// Test 2 always fails, but I don't understand why.
		// Tests 1 and 4 always pass.
		this->RunTest(qt_clip,     qt_clip,     "Mary had a little lamb");
		this->RunTest(qt_clip,     cygwin_clip, "Whose fleece was as white as snow");
		this->RunTest(cygwin_clip, qt_clip,     "And everywhere that Mary went");
		this->RunTest(cygwin_clip, cygwin_clip, "The lamb was sure to go");
	}

private:
	// Procedure to run a test.
	// The string in 'str' is written to the clipboard using 'write'.
	// Then the clipboard is read using 'read'.
	// The string read should match 'str', i.e. we read back from the clipboard the same string we wrote to it.
	void RunTest(const CClipboardAccess &write, const CClipboardAccess &read, const std::string &str)
	{
		static unsigned int count = 0;
		std::cout << std::endl << "TEST " << (++count)
		          << ": Write using " << write.GetName()
				  << ", read using " << read.GetName() << '.' << std::endl;

		write.ClearClipboard();
		sleep(1);
		read.ClearClipboard();
		sleep(1);

		std::cout << ">>> Setting " << write.GetName() << " to '" << str << "'." << std::endl;
		write.SetClipboard(str);
		sleep(1);
		const std::string result = read.GetClipboard();
		std::cout << ">>> Read " << read.GetName() << " = '" << result << "'." << std::endl;

		if (result == str)
			std::cout << ">>> OK - strings match." << std::endl;
		else
			std::cout << "*** FAILED." << std::endl;
	}
};

int main(int argc, char **pargv)
{
	CTest test(argc, pargv);
	test.GoTest();
	return 0;
}