commit 197c193e210cea1697a1217e9f252a35f266273a
Author: Juergen Spitzmueller <[email protected]>
Date:   Sat Dec 17 12:58:33 2016 +0100

    Context menu for quote insets
    
    Allows to switch quote type.
---
 lib/ui/stdcontext.inc       |    8 +++
 src/frontends/qt4/Menus.cpp |  102 ++++++++++++++++++++++++++++++++++++++++++-
 src/insets/InsetQuotes.cpp  |   94 ++++++++++++++++++++++++++++++++++++++-
 src/insets/InsetQuotes.h    |   16 +++++++
 4 files changed, 215 insertions(+), 5 deletions(-)

diff --git a/lib/ui/stdcontext.inc b/lib/ui/stdcontext.inc
index a229b4a..89cf287 100644
--- a/lib/ui/stdcontext.inc
+++ b/lib/ui/stdcontext.inc
@@ -218,6 +218,14 @@ Menuset
                Item "Vertical Phantom|V" "inset-modify phantom Phantom 
VPhantom"
        End
 
+
+#
+# InsetQuotes context menu
+#
+       Menu "context-quote"
+               SwitchQuotes
+       End
+
 #
 # InsetSpace context menu
 #
diff --git a/src/frontends/qt4/Menus.cpp b/src/frontends/qt4/Menus.cpp
index 53a8455..5a7e8e0 100644
--- a/src/frontends/qt4/Menus.cpp
+++ b/src/frontends/qt4/Menus.cpp
@@ -60,6 +60,7 @@
 #include "insets/Inset.h"
 #include "insets/InsetCitation.h"
 #include "insets/InsetGraphics.h"
+#include "insets/InsetQuotes.h"
 
 #include "support/lassert.h"
 #include "support/convert.h"
@@ -188,7 +189,9 @@ public:
                in the InsetCaption context menu. */
                SwitchCaptions,
                /** Commands to separate environments. */
-               EnvironmentSeparators
+               EnvironmentSeparators,
+               /** This is the list of quotation marks available */
+               SwitchQuotes
        };
 
        explicit MenuItem(Kind kind) : kind_(kind), optional_(false) {}
@@ -362,6 +365,7 @@ public:
        void expandArguments(BufferView const *, bool switcharg = false);
        void expandCaptions(Buffer const * buf, bool switchcap = false);
        void expandEnvironmentSeparators(BufferView const *);
+       void expandQuotes(BufferView const *);
        ///
        ItemList items_;
        ///
@@ -474,7 +478,8 @@ void MenuDefinition::read(Lexer & lex)
                md_switcharguments,
                md_captions,
                md_switchcaptions,
-               md_env_separators
+               md_env_separators,
+               md_switchquotes
        };
 
        LexerKeyword menutags[] = {
@@ -509,6 +514,7 @@ void MenuDefinition::read(Lexer & lex)
                { "submenu", md_submenu },
                { "switcharguments", md_switcharguments },
                { "switchcaptions", md_switchcaptions },
+               { "switchquotes", md_switchquotes },
                { "toc", md_toc },
                { "toolbars", md_toolbars },
                { "updateformats", md_updateformats },
@@ -656,6 +662,10 @@ void MenuDefinition::read(Lexer & lex)
                        add(MenuItem(MenuItem::EnvironmentSeparators));
                        break;
 
+               case md_switchquotes:
+                       add(MenuItem(MenuItem::SwitchQuotes));
+                       break;
+
                case md_optsubmenu:
                case md_submenu: {
                        lex.next(true);
@@ -1641,6 +1651,90 @@ void MenuDefinition::expandCaptions(Buffer const * buf, 
bool switchcap)
 }
 
 
+void MenuDefinition::expandQuotes(BufferView const * bv)
+{
+       if (!bv)
+               return;
+    
+       if (!bv->cursor().inTexted())
+               return;
+
+       Inset const * inset = bv->cursor().nextInset();
+       if (!inset || inset->lyxCode() != QUOTE_CODE) {
+               add(MenuItem(MenuItem::Command,
+                                   qt_("No Quote in Scope!"),
+                                   FuncRequest(LFUN_NOACTION)));
+               return;
+       }
+       InsetQuotes const * qinset =
+               static_cast<InsetQuotes const *>(inset);
+
+       map<string, docstring> styles = qinset->getTypes();
+       string const qtype = qinset->getType();
+       
+       map<string, docstring>::const_iterator qq = styles.begin();
+       map<string, docstring>::const_iterator end = styles.end();
+
+       MenuDefinition eqs;
+       MenuDefinition sqs;
+       MenuDefinition gqs;
+       MenuDefinition pqs;
+       MenuDefinition fqs;
+       MenuDefinition aqs;
+       for (; qq != end; ++qq) {
+               docstring const style = from_ascii(qq->first);
+               FuncRequest const cmd = FuncRequest(LFUN_INSET_MODIFY, 
from_ascii("changetype ") + style);
+               docstring const desc = contains(style, 'l') ? 
+                       bformat(_("%1$stext"), qq->second) : 
bformat(_("text%1$s"), qq->second);
+               if (prefixIs(style, qtype[0]))
+                       add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 'e') && !prefixIs(qtype, "e"))
+                       eqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 's') && !prefixIs(qtype, "s"))
+                       sqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 'g') && !prefixIs(qtype, "g"))
+                       gqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 'p') && !prefixIs(qtype, "p"))
+                       pqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 'f') && !prefixIs(qtype, "f"))
+                       fqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+               else if (prefixIs(style, 'a') && !prefixIs(qtype, "a"))
+                       aqs.add(MenuItem(MenuItem::Command, toqstr(desc), cmd));
+       }
+
+       if (!eqs.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_("``text''"));
+               item.setSubmenu(eqs);
+               add(item);
+       }
+       if (!sqs.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_("''text''"));
+               item.setSubmenu(sqs);
+               add(item);
+       }
+       if (!gqs.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_(",,text``"));
+               item.setSubmenu(gqs);
+               add(item);
+       }
+       if (!pqs.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_(",,text''"));
+               item.setSubmenu(pqs);
+               add(item);
+       }
+       if (!fqs.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_("<<text>>"));
+               item.setSubmenu(fqs);
+               add(item);
+       }
+       if (!aqs.empty()) {
+               MenuItem item(MenuItem::Submenu, qt_(">>text<<"));
+               item.setSubmenu(aqs);
+               add(item);
+       }
+}
+
+
 void MenuDefinition::expandEnvironmentSeparators(BufferView const * bv)
 {
        if (!bv)
@@ -2071,6 +2165,10 @@ void Menus::Impl::expand(MenuDefinition const & frommenu,
                        tomenu.expandEnvironmentSeparators(bv);
                        break;
 
+               case MenuItem::SwitchQuotes:
+                       tomenu.expandQuotes(bv);
+                       break;
+
                case MenuItem::Submenu: {
                        MenuItem item(*cit);
                        item.setSubmenu(MenuDefinition(cit->submenuname()));
diff --git a/src/insets/InsetQuotes.cpp b/src/insets/InsetQuotes.cpp
index b445936..147e177 100644
--- a/src/insets/InsetQuotes.cpp
+++ b/src/insets/InsetQuotes.cpp
@@ -15,8 +15,11 @@
 #include "Buffer.h"
 #include "BufferParams.h"
 #include "BufferView.h"
+#include "Cursor.h"
 #include "Dimension.h"
 #include "Font.h"
+#include "FuncStatus.h"
+#include "FuncRequest.h"
 #include "Language.h"
 #include "LaTeXFeatures.h"
 #include "Lexer.h"
@@ -223,6 +226,35 @@ InsetQuotes::QuoteLanguage InsetQuotes::getLanguage(string 
const & s)
 }
 
 
+map<string, docstring> InsetQuotes::getTypes() const
+{
+       map<string, docstring> res;
+
+       int l, s, t;
+       QuoteLanguage lang;
+       QuoteSide side;
+       QuoteTimes times;
+       string type;
+
+       // get all quote types
+       for (l = 0; l < 6; ++l) {
+               lang = QuoteLanguage(l);
+               for (s = 0; s < 2; ++s) {
+                       side = QuoteSide(s);
+                       for (t = 0; t < 2; ++t) {
+                               type += language_char[lang];
+                               type += side_char[s];
+                               times = QuoteTimes(t);
+                               type += times_char[t];
+                               res[type] = docstring(1, 
display_quote_char[times][quote_index[side][lang]]);
+                               type.clear();
+                       }
+               }
+       }
+       return res;
+}
+
+
 docstring InsetQuotes::displayString() const
 {
        // In PassThru, we use straight quotes
@@ -265,14 +297,18 @@ void InsetQuotes::draw(PainterInfo & pi, int x, int y) 
const
        pi.pain.text(x, y, displayString(), font);
 }
 
-
-void InsetQuotes::write(ostream & os) const
+string InsetQuotes::getType() const
 {
        string text;
        text += language_char[language_];
        text += side_char[side_];
        text += times_char[times_];
-       os << "Quotes " << text;
+       return text;
+}
+       
+void InsetQuotes::write(ostream & os) const
+{
+       os << "Quotes " << getType();
 }
 
 
@@ -285,6 +321,52 @@ void InsetQuotes::read(Lexer & lex)
 }
 
 
+void InsetQuotes::doDispatch(Cursor & cur, FuncRequest & cmd)
+{
+       switch (cmd.action()) {
+       case LFUN_INSET_MODIFY: {
+               string const first_arg = cmd.getArg(0);
+               bool const change_type = first_arg == "changetype";
+               if (!change_type) {
+                       // not for us
+                       // this will not be handled higher up
+                       cur.undispatched();
+                       return;
+               }
+               cur.recordUndoInset(this);
+               parseString(cmd.getArg(1));
+               cur.buffer()->updateBuffer();
+               break;
+       }
+       default:
+               Inset::doDispatch(cur, cmd);
+               break;
+       }
+}
+
+
+bool InsetQuotes::getStatus(Cursor & cur, FuncRequest const & cmd,
+               FuncStatus & flag) const
+{
+       switch (cmd.action()) {
+
+       case LFUN_INSET_MODIFY: {
+               string const first_arg = cmd.getArg(0);
+               if (first_arg == "changetype") {
+                       string const type = cmd.getArg(1);
+                       flag.setOnOff(type == getType());
+                       flag.setEnabled(!pass_thru_);
+                       return true;
+               }
+               return Inset::getStatus(cur, cmd, flag);
+       }
+
+       default:
+               return Inset::getStatus(cur, cmd, flag);
+       }
+}
+
+
 void InsetQuotes::latex(otexstream & os, OutputParams const & runparams) const
 {
        const int quoteind = quote_index[side_][language_];
@@ -439,4 +521,10 @@ void InsetQuotes::validate(LaTeXFeatures & features) const
        }
 }
 
+
+string InsetQuotes::contextMenuName() const
+{
+       return "context-quote";
+}
+
 } // namespace lyx
diff --git a/src/insets/InsetQuotes.h b/src/insets/InsetQuotes.h
index 024304b..3054054 100644
--- a/src/insets/InsetQuotes.h
+++ b/src/insets/InsetQuotes.h
@@ -78,6 +78,8 @@ public:
        ///
        void read(Lexer & lex);
        ///
+       bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;
+       ///
        void latex(otexstream &, OutputParams const &) const;
        ///
        int plaintext(odocstringstream & ods, OutputParams const & op,
@@ -98,9 +100,16 @@ public:
        ///
        void validate(LaTeXFeatures &) const;
        ///
+       std::string contextMenuName() const;
+       ///
        InsetCode lyxCode() const { return QUOTE_CODE; }
        /// should this inset be handled like a normal character
        bool isChar() const { return true; }
+       
+       /// Returns the current quote type
+       std::string getType() const;
+       /// Returns a map of quotation marks
+       std::map<std::string, docstring> getTypes() const;
 
 private:
        ///
@@ -129,6 +138,13 @@ private:
        std::string context_lang_;
        /// Is this in a pass-thru context?
        bool pass_thru_;
+
+protected:
+       /// \name Protected functions inherited from Inset class
+       //@{
+       ///
+       void doDispatch(Cursor & cur, FuncRequest & cmd);
+       //@}
 };
 
 } // namespace lyx

Reply via email to