// Compile: g++ -I/usr/include/qt4 -L/usr/lib/qt4/lib -o qt4_clip qt4_clip.cpp -lQtGui -lQtCore #include #include #include #include #include #include #include // 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; }