/// // Copyright (C) 2002 - 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING /// #include "clipboard.h" #include #include "document/page.h" #include "document/textframe.h" #include "document/loader.h" #include "util/warning.h" namespace { template P nonull(P p) { if(!p) throw std::runtime_error("A pointer was null in " __FILE__); return p; } std::string clip; // a global clip should suffice const std::string pptout_target = "PPTOUT_PAGENTS_2"; // with version number void on_clipboard_get(Gtk::SelectionData& selection_data, guint info) { const Glib::ustring& target = selection_data.get_target(); if(target == pptout_target) selection_data.set(pptout_target, clip); } void on_clipboard_clear() { // not really necessary clip.clear(); } void on_clipboard_received(const Gtk::SelectionData& selection_data, std::pair bundle) { DocRef document = bundle.first; Page *page = bundle.second; Glib::ustring clipboard_data = selection_data.get_data_as_string(); try { xmlpp::DomParser parser; parser.parse_memory(clipboard_data); xmlpp::Element *root = parser.get_document()->get_root_node(); if(!root) throw std::runtime_error("Root node is NULL."); xmlpp::Element::NodeList children = root->get_children(); document->select_all(false); for(xmlpp::Element::NodeList::const_iterator i = children.begin(); i != children.end(); i++) { if(xmlpp::Element *elem = dynamic_cast(*i)) { if(elem->get_name() == "text_stream") { std::auto_ptr stream(new TextStream (ElementWrap("", *elem))); // Don't try to add a stream with a name that already exists /// \todo rename the stream automatically? if(!document->get_text_stream(stream->get_name())) document->add_text_stream(stream.release()); } else { Pagent *pagent = load(ElementWrap("", *elem), page); page->add(pagent); document->select(pagent, false); // don't deselect } } } } catch(const std::exception& e) { throw std::runtime_error("Error encountered when pasting:\n" + std::string(e.what())); } } } void Clipboard::copy(DocRef document) { nonull(document); /// \todo make sure the selection is sorted const Document::Selection selected = document->selected(); if(selected.empty()) return; Glib::RefPtr clipboard = Gtk::Clipboard::get(); std::list target_list; target_list.push_back(Gtk::TargetEntry(pptout_target)); clipboard->set(target_list, sigc::ptr_fun(&on_clipboard_get), sigc::ptr_fun(&on_clipboard_clear)); // store an XML representation of the selected pagents xmlpp::Document rep; xmlpp::Element *root = rep.create_root_node("copy_data"); // save relevant streams typedef std::set Streams; Streams streams; for(Document::Selection::const_iterator i = selected.begin(); i != selected.end(); i++) { const TextFrame *frame = dynamic_cast(*i); if(!frame) continue; const TextStream *stream = frame->get_stream(); if(stream && streams.find(stream) == streams.end()) { streams.insert(stream); stream->save(*root, FileContext()); } } // save pagents for(Document::Selection::const_iterator i = selected.begin(); i != selected.end(); i++) { (*i)->save(*root, FileContext()); } clip = rep.write_to_string(); debug << clip << std::endl; } void Clipboard::cut(DocRef document) { nonull(document); copy(document); document->delete_selected(); } void Clipboard::paste(DocRef document, Page *page) { Gtk::Clipboard::get()->request_contents (pptout_target, sigc::bind(sigc::ptr_fun(&on_clipboard_received), std::make_pair(nonull(document), nonull(page)))); }