From d6412742473a8aeda8d424fb33420dbdf4859875 Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 9 Aug 2019 19:14:46 +0200 Subject: [PATCH] Fixes: #412 : Added Edit->Cut Lines and Edit->Copy Lines. Additionally, successive cut lines now accumulates the clipboard --- CMakeLists.txt | 2 +- src/files.h | 2 + src/menu.cc | 8 ++++ src/source_base.cc | 32 ++++++++++++++++ src/source_base.h | 4 ++ src/window.cc | 91 +++++++++++++++++++++++++++++++++++----------- 6 files changed, 117 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index de8b275..4e90ca1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required (VERSION 2.8.8) project(juci) -set(JUCI_VERSION "1.4.6.7") +set(JUCI_VERSION "1.4.6.8") set(CPACK_PACKAGE_NAME "jucipp") set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim ") diff --git a/src/files.h b/src/files.h index ea1c0bd..4caa1b6 100644 --- a/src/files.h +++ b/src/files.h @@ -87,7 +87,9 @@ const std::string default_config_file = R"RAW({ "edit_undo": "z", "edit_redo": "z", "edit_cut": "x", + "edit_cut_lines": "x", "edit_copy": "c", + "edit_copy_lines": "c", "edit_paste": "v", "edit_extend_selection": "a", "edit_shrink_selection": "a", diff --git a/src/menu.cc b/src/menu.cc index de38028..ec378fe 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -188,10 +188,18 @@ const Glib::ustring menu_xml = R"RAW( _Cut app.edit_cut + + _Cut _Lines + app.edit_cut_lines + _Copy app.edit_copy + + _Copy _Lines + app.edit_copy_lines + _Paste app.edit_paste diff --git a/src/source_base.cc b/src/source_base.cc index c36bf89..724690d 100644 --- a/src/source_base.cc +++ b/src/source_base.cc @@ -69,6 +69,15 @@ Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib: rgba.set_rgba(0.5, 0.5, 0.5, 0.4); snippet_argument_tag->property_background_rgba() = rgba; snippet_argument_tag->property_background_set() = true; + + get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator &iter, const Glib::RefPtr &mark) { + if(mark->get_name() == "insert") + keep_clipboard = false; + }); + + get_buffer()->signal_changed().connect([this] { + keep_clipboard = false; + }); } Source::BaseView::~BaseView() { @@ -678,6 +687,29 @@ void Source::BaseView::cleanup_whitespace_characters(const Gtk::TextIter &iter) get_buffer()->erase(start_blank_iter, end_blank_iter); } +void Source::BaseView::cut() { + if(!get_buffer()->get_has_selection()) + cut_line(); + else + get_buffer()->cut_clipboard(Gtk::Clipboard::get()); + keep_clipboard = true; +} + +void Source::BaseView::cut_line() { + Gtk::TextIter start, end; + get_buffer()->get_selection_bounds(start, end); + start = get_buffer()->get_iter_at_line(start.get_line()); + if(!end.ends_line()) + end.forward_to_line_end(); + end.forward_char(); + if(keep_clipboard) + Gtk::Clipboard::get()->set_text(Gtk::Clipboard::get()->wait_for_text() + get_buffer()->get_text(start, end)); + else + Gtk::Clipboard::get()->set_text(get_buffer()->get_text(start, end)); + get_buffer()->erase(start, end); + keep_clipboard = true; +} + void Source::BaseView::paste() { if(CompletionDialog::get()) CompletionDialog::get()->hide(); diff --git a/src/source_base.h b/src/source_base.h index 2270d3f..2a977d0 100644 --- a/src/source_base.h +++ b/src/source_base.h @@ -66,6 +66,8 @@ namespace Source { std::string status_branch; std::function update_search_occurrences; + void cut(); + void cut_line(); void paste(); std::string get_selected_text(); @@ -86,6 +88,8 @@ namespace Source { GtkSourceSearchSettings *search_settings; static void search_occurrences_updated(GtkWidget *widget, GParamSpec *property, gpointer data); + bool keep_clipboard = false; + protected: std::time_t last_write_time; void monitor_file(); diff --git a/src/window.cc b/src/window.cc index e868179..a0b92f3 100644 --- a/src/window.cc +++ b/src/window.cc @@ -481,29 +481,46 @@ void Window::set_menu_actions() { } auto widget = get_focus(); - if(auto entry = dynamic_cast(widget)) - entry->cut_clipboard(); + if(auto entry = dynamic_cast(widget)) { + int start, end; + if(!entry->get_selection_bounds(start, end)) { + Gtk::Clipboard::get()->set_text(entry->get_text()); + entry->set_text(""); + } + else + entry->cut_clipboard(); + } else if(auto view = dynamic_cast(widget)) { if(!view->get_editable()) return; - auto source_view = dynamic_cast(view); - if(source_view) + if(auto source_view = dynamic_cast(view)) { source_view->disable_spellcheck = true; - if(!view->get_buffer()->get_has_selection()) { - auto start = view->get_buffer()->get_iter_at_line(view->get_buffer()->get_insert()->get_iter().get_line()); - auto end = start; - if(!end.ends_line()) - end.forward_to_line_end(); - end.forward_char(); - if(!end.starts_line()) // In case of \r\n - end.forward_char(); - Gtk::Clipboard::get()->set_text(view->get_buffer()->get_text(start, end)); - view->get_buffer()->erase(start, end); + source_view->cut(); + source_view->disable_spellcheck = false; } - else - view->get_buffer()->cut_clipboard(Gtk::Clipboard::get()); - if(source_view) + } + }); + menu.add_action("edit_cut_lines", [this]() { + // Return if a shown tooltip has selected text + for(auto tooltip : Tooltips::shown_tooltips) { + auto buffer = tooltip->text_buffer; + if(buffer && buffer->get_has_selection()) + return; + } + + auto widget = get_focus(); + if(auto entry = dynamic_cast(widget)) { + Gtk::Clipboard::get()->set_text(entry->get_text()); + entry->set_text(""); + } + else if(auto view = dynamic_cast(widget)) { + if(!view->get_editable()) + return; + if(auto source_view = dynamic_cast(view)) { + source_view->disable_spellcheck = true; + source_view->cut_line(); source_view->disable_spellcheck = false; + } } }); menu.add_action("edit_copy", [this]() { @@ -517,8 +534,13 @@ void Window::set_menu_actions() { } auto widget = get_focus(); - if(auto entry = dynamic_cast(widget)) - entry->copy_clipboard(); + if(auto entry = dynamic_cast(widget)) { + int start, end; + if(!entry->get_selection_bounds(start, end)) + Gtk::Clipboard::get()->set_text(entry->get_text()); + else + entry->copy_clipboard(); + } else if(auto view = dynamic_cast(widget)) { if(!view->get_buffer()->get_has_selection()) { auto start = view->get_buffer()->get_iter_at_line(view->get_buffer()->get_insert()->get_iter().get_line()); @@ -526,14 +548,41 @@ void Window::set_menu_actions() { if(!end.ends_line()) end.forward_to_line_end(); end.forward_char(); - if(!end.starts_line()) // In case of \r\n - end.forward_char(); Gtk::Clipboard::get()->set_text(view->get_buffer()->get_text(start, end)); } else view->get_buffer()->copy_clipboard(Gtk::Clipboard::get()); } }); + menu.add_action("edit_copy_lines", [this]() { + // Copy from a tooltip if it has selected text + for(auto tooltip : Tooltips::shown_tooltips) { + auto buffer = tooltip->text_buffer; + if(buffer && buffer->get_has_selection()) { + Gtk::TextIter start, end; + buffer->get_selection_bounds(start, end); + start = buffer->get_iter_at_line(start.get_line()); + if(!end.ends_line()) + end.forward_to_line_end(); + end.forward_char(); + Gtk::Clipboard::get()->set_text(buffer->get_text(start, end)); + return; + } + } + + auto widget = get_focus(); + if(auto entry = dynamic_cast(widget)) + Gtk::Clipboard::get()->set_text(entry->get_text()); + else if(auto view = dynamic_cast(widget)) { + Gtk::TextIter start, end; + view->get_buffer()->get_selection_bounds(start, end); + start = view->get_buffer()->get_iter_at_line(start.get_line()); + if(!end.ends_line()) + end.forward_to_line_end(); + end.forward_char(); + Gtk::Clipboard::get()->set_text(view->get_buffer()->get_text(start, end)); + } + }); menu.add_action("edit_paste", [this]() { auto widget = get_focus(); if(auto entry = dynamic_cast(widget))