From eaa33dca6def75e9bf48582073c75b256821fd25 Mon Sep 17 00:00:00 2001 From: Bo Peng Date: Thu, 2 Nov 2006 16:01:36 +0000 Subject: [PATCH] Session/Toolbars: * src/LyXAction.C: LFUN_TOOLBAR_TOGGLE_STATE * src/session.h/C: add ToolbarSection class * src/lyxfunc.C: handle LFUN_TOOLBAR_TOGGLE_STATE * src/frontends/LyXView.h/C: toggleToolbarState(name) * src/frontends/Toolbars.h/C: initFlags, toogle and save toolbar, changed update logic * src/frontends/qt4/QLToolbar.h/C: saveInfo. Surprisingly little is asked from frontend. * src/frontends/qt4/GuiView.C: save toolbar when lyx exits * src/MenuBackend.h/C: add Toolbars submenu * src/lfuns.h: add LFUN_TOOLBAR_TOGGLE_STATE * src/ToolbarBackend.h: add AUTO flag * lib/ui/stdmenus.ui: add view->Toolbar menu git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15691 a592a061-630c-0410-9148-cb99ea01b6c8 --- lib/ui/stdmenus.ui | 5 ++ src/LyXAction.C | 1 + src/MenuBackend.C | 40 ++++++++++ src/MenuBackend.h | 2 + src/ToolbarBackend.h | 7 +- src/frontends/LyXView.C | 14 ++++ src/frontends/LyXView.h | 2 + src/frontends/Toolbars.C | 146 ++++++++++++++++++++++++++++++++-- src/frontends/Toolbars.h | 14 ++++ src/frontends/qt4/GuiView.C | 1 + src/frontends/qt4/QLToolbar.C | 26 ++++++ src/frontends/qt4/QLToolbar.h | 2 + src/lfuns.h | 1 + src/lyxfunc.C | 5 ++ src/session.C | 49 ++++++++++++ src/session.h | 68 ++++++++++++++++ 16 files changed, 376 insertions(+), 7 deletions(-) diff --git a/lib/ui/stdmenus.ui b/lib/ui/stdmenus.ui index e66f93a8c7..3e39c970f2 100644 --- a/lib/ui/stdmenus.ui +++ b/lib/ui/stdmenus.ui @@ -265,6 +265,8 @@ Menuset Submenu "Update|U" "view_update" ViewFormats Separator + Submenu "Toolbars|b" "toolbars" + Separator Documents End @@ -272,6 +274,9 @@ Menuset UpdateFormats End + Menu "toolbars" + Toolbars + End # # INSERT MENU # diff --git a/src/LyXAction.C b/src/LyXAction.C index e2f1ff6c2e..9a97638cd4 100644 --- a/src/LyXAction.C +++ b/src/LyXAction.C @@ -366,6 +366,7 @@ void LyXAction::init() { LFUN_WINDOW_NEW, "window-new", NoBuffer }, { LFUN_WINDOW_CLOSE, "window-close", NoBuffer }, { LFUN_UNICODE_INSERT, "unicode-insert", Noop }, + { LFUN_TOOLBAR_TOGGLE_STATE, "", Noop }, { LFUN_NOACTION, "", Noop } }; diff --git a/src/MenuBackend.C b/src/MenuBackend.C index 27ed4c2163..6bd046ff3a 100644 --- a/src/MenuBackend.C +++ b/src/MenuBackend.C @@ -36,6 +36,7 @@ #include "lyxfunc.h" #include "lyxlex.h" #include "toc.h" +#include "ToolbarBackend.h" #include "support/filetools.h" #include "support/lstrings.h" @@ -231,6 +232,7 @@ Menu & Menu::read(LyXLex & lex) md_floatlistinsert, md_floatinsert, md_pasterecent, + md_toolbars, md_last }; @@ -253,6 +255,7 @@ Menu & Menu::read(LyXLex & lex) { "submenu", md_submenu }, { "toc", md_toc }, { "updateformats", md_updateformats }, + { "toolbars", md_toolbars }, { "viewformats", md_viewformats } }; @@ -331,6 +334,10 @@ Menu & Menu::read(LyXLex & lex) add(MenuItem(MenuItem::PasteRecent)); break; + case md_toolbars: + add(MenuItem(MenuItem::Toolbars)); + break; + case md_branches: add(MenuItem(MenuItem::Branches)); break; @@ -751,6 +758,35 @@ void expandPasteRecent(Menu & tomenu, Buffer const * buf) } +void expandToolbars(Menu & tomenu, Buffer const * buf) +{ + // + // extracts the toolbars from the backend + ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin(); + ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end(); + + int i = 1; + for (; cit != end; ++cit, ++i) { + docstring label = convert(i) + ". " + _(cit->name); + // frontend does not update ToolbarBackend::flags when it changes toolbar + // Therefore, I can not tell from the flags if the toolbar is on or off + // it is then less confusing to say: + // this is: always on/off/auto + // frontend toolbar change is temporary. + // + if (cit->flags & ToolbarBackend::ON) + label += _(" (always on)"); + else if (cit->flags & ToolbarBackend::OFF) + label += _(" (always off)"); + else if (cit->flags & ToolbarBackend::AUTO) + label += _(" (auto)"); + label += char_type('|') + convert(i); + tomenu.add(MenuItem(MenuItem::Command, label, + FuncRequest(LFUN_TOOLBAR_TOGGLE_STATE, _(cit->name)))); + } +} + + void expandBranches(Menu & tomenu, Buffer const * buf) { if (!buf) @@ -819,6 +855,10 @@ void MenuBackend::expand(Menu const & frommenu, Menu & tomenu, expandPasteRecent(tomenu, buf); break; + case MenuItem::Toolbars: + expandToolbars(tomenu, buf); + break; + case MenuItem::Branches: expandBranches(tomenu, buf); break; diff --git a/src/MenuBackend.h b/src/MenuBackend.h index ecec25559e..c72546c7f8 100644 --- a/src/MenuBackend.h +++ b/src/MenuBackend.h @@ -72,6 +72,8 @@ public: /** This is the list of selections that can be pasted. */ PasteRecent, + /** toolbars */ + Toolbars, /** Available branches in document */ Branches }; diff --git a/src/ToolbarBackend.h b/src/ToolbarBackend.h index bdbed6a6db..7d9fc9f6b9 100644 --- a/src/ToolbarBackend.h +++ b/src/ToolbarBackend.h @@ -53,7 +53,8 @@ public: BOTTOM = 32, //< show at bottom LEFT = 64, //< show at left RIGHT = 128, //< show at right - REVIEW = 256 //< shown when change tracking is enabled + REVIEW = 256, //< shown when change tracking is enabled + AUTO = 512 //< only if AUTO is set, will MATH, TABLE and REIVEW is used }; /// a toolbar @@ -79,6 +80,10 @@ public: Toolbars::const_iterator end() const { return usedtoolbars.end(); } + Toolbars::iterator begin() { return usedtoolbars.begin(); } + + Toolbars::iterator end() { return usedtoolbars.end(); } + /// read a toolbar from the file void read(LyXLex &); diff --git a/src/frontends/LyXView.C b/src/frontends/LyXView.C index c32a47e3ce..397897b4a1 100644 --- a/src/frontends/LyXView.C +++ b/src/frontends/LyXView.C @@ -305,6 +305,20 @@ void LyXView::updateToolbars() } +void LyXView::toggleToolbarState(string const & name) +{ + // it is possible to get current toolbar status like this,... + // but I decide to obey the order of ToolbarBackend::flags + // and disregard real toolbar status. + // toolbars_->saveToolbarInfo(); + // + // toggle state on/off/auto + toolbars_->toggleToolbarState(name); + // update toolbar + updateToolbars(); +} + + void LyXView::updateMenubar() { menubar_->update(); diff --git a/src/frontends/LyXView.h b/src/frontends/LyXView.h index 2624db2486..606b3ceaa3 100644 --- a/src/frontends/LyXView.h +++ b/src/frontends/LyXView.h @@ -136,6 +136,8 @@ public: /// update the toolbar void updateToolbars(); + /// toggle toolbar state + void toggleToolbarState(std::string const & name); /// update the menubar void updateMenubar(); /// update the status bar diff --git a/src/frontends/Toolbars.C b/src/frontends/Toolbars.C index a5b7273739..478013b9e5 100644 --- a/src/frontends/Toolbars.C +++ b/src/frontends/Toolbars.C @@ -22,6 +22,7 @@ #include "lyxfunc.h" #include "lyxtextclass.h" #include "LyXView.h" +#include "lyx_main.h" namespace lyx { @@ -36,15 +37,78 @@ Toolbars::Toolbars(LyXView & owner) last_textclass_(-1) {} +#define TurnOnFlag(x) flags |= ToolbarBackend::x +#define TurnOffFlag(x) flags &= ~ToolbarBackend::x + +void Toolbars::initFlags(ToolbarBackend::Toolbar & tbb) +{ + ToolbarSection::ToolbarInfo & info = LyX::ref().session().toolbars().load(tbb.name); + + unsigned int flags = static_cast(tbb.flags); + // remove position + TurnOffFlag(TOP); + TurnOffFlag(BOTTOM); + TurnOffFlag(RIGHT); + TurnOffFlag(LEFT); + + bool valid_location = true; + // init tbb.flags with saved location + if (info.location == ToolbarSection::ToolbarInfo::TOP) + TurnOnFlag(TOP); + else if (info.location == ToolbarSection::ToolbarInfo::BOTTOM) + TurnOnFlag(BOTTOM); + else if (info.location == ToolbarSection::ToolbarInfo::RIGHT) + TurnOnFlag(RIGHT); + else if (info.location == ToolbarSection::ToolbarInfo::LEFT) + TurnOnFlag(LEFT); + else { + TurnOnFlag(TOP); + valid_location = false; + } + + // invalid location is for a new toolbar that has no saved information, + // so info.visible is not used for this case. + if (valid_location) { + // init tbb.flags with saved visibility, + TurnOffFlag(ON); + TurnOffFlag(OFF); + TurnOffFlag(AUTO); + if (info.state == ToolbarSection::ToolbarInfo::ON) + TurnOnFlag(ON); + else if (info.state == ToolbarSection::ToolbarInfo::OFF) + TurnOnFlag(OFF); + else + TurnOnFlag(AUTO); + } + /* + std::cout << "State " << info.state << " FLAGS: " << flags + << " ON:" << (flags & ToolbarBackend::ON) + << " OFF:" << (flags & ToolbarBackend::OFF) + << " L:" << (flags & ToolbarBackend::LEFT) + << " R:" << (flags & ToolbarBackend::RIGHT) + << " T:" << (flags & ToolbarBackend::TOP) + << " B:" << (flags & ToolbarBackend::BOTTOM) + << " MA:" << (flags & ToolbarBackend::MATH) + << " RE:" << (flags & ToolbarBackend::REVIEW) + << " TB:" << (flags & ToolbarBackend::TABLE) + << " AU:" << (flags & ToolbarBackend::AUTO) + << std::endl; + */ + // now set the flags + tbb.flags = static_cast(flags); +} + void Toolbars::init() { // extracts the toolbars from the backend - ToolbarBackend::Toolbars::const_iterator cit = toolbarbackend.begin(); - ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end(); + ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin(); + ToolbarBackend::Toolbars::iterator end = toolbarbackend.end(); - for (; cit != end; ++cit) + for (; cit != end; ++cit) { + initFlags(*cit); add(*cit); + } } @@ -65,6 +129,39 @@ void Toolbars::display(string const & name, bool show) } +void Toolbars::toggleToolbarState(string const & name) +{ + ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin(); + ToolbarBackend::Toolbars::iterator end = toolbarbackend.end(); + + for (; cit != end; ++cit) { + if (cit->name == name) { + int flags = cit->flags; + if (flags & ToolbarBackend::ON) { + TurnOffFlag(ON); + TurnOnFlag(OFF); + } else if (flags & ToolbarBackend::AUTO) { + TurnOffFlag(AUTO); + TurnOnFlag(ON); + } else if ((flags & ToolbarBackend::MATH) || (flags & ToolbarBackend::TABLE) + || (flags & ToolbarBackend::REVIEW)) { + // for math etc, toggle from off -> auto + TurnOffFlag(OFF); + TurnOnFlag(AUTO); + } else { + // for others, toggle from off -> on + TurnOffFlag(OFF); + TurnOnFlag(ON); + } + cit->flags = static_cast(flags); + break; + } + } +} +#undef TurnOnFlag +#undef TurnOffFlag + + void Toolbars::update(bool in_math, bool in_table, bool review) { update(); @@ -74,16 +171,53 @@ void Toolbars::update(bool in_math, bool in_table, bool review) ToolbarBackend::Toolbars::const_iterator end = toolbarbackend.end(); for (; cit != end; ++cit) { - if (cit->flags & ToolbarBackend::MATH) + if (cit->flags & ToolbarBackend::ON) + displayToolbar(*cit, true); + else if (cit->flags & ToolbarBackend::OFF) + displayToolbar(*cit, false); + else if ((cit->flags & ToolbarBackend::AUTO) && (cit->flags & ToolbarBackend::MATH)) displayToolbar(*cit, in_math); - else if (cit->flags & ToolbarBackend::TABLE) + else if ((cit->flags & ToolbarBackend::AUTO) && (cit->flags & ToolbarBackend::TABLE)) displayToolbar(*cit, in_table); - else if (cit->flags & ToolbarBackend::REVIEW) + else if ((cit->flags & ToolbarBackend::AUTO) && (cit->flags & ToolbarBackend::REVIEW)) displayToolbar(*cit, review); } } +void Toolbars::saveToolbarInfo() +{ + ToolbarSection & tb = LyX::ref().session().toolbars(); + + for (ToolbarBackend::Toolbars::iterator cit = toolbarbackend.begin(); + cit != toolbarbackend.end(); ++cit) { + ToolbarsMap::iterator it = toolbars_.find(cit->name); + BOOST_ASSERT(it != toolbars_.end()); + // get toolbar info from session. + ToolbarSection::ToolbarInfo & info = tb.load(cit->name); + if (cit->flags & ToolbarBackend::ON) + info.state = ToolbarSection::ToolbarInfo::ON; + else if (cit->flags & ToolbarBackend::OFF) + info.state = ToolbarSection::ToolbarInfo::OFF; + else if (cit->flags & ToolbarBackend::AUTO) + info.state = ToolbarSection::ToolbarInfo::AUTO; + // save other information + // if auto, frontend should *not* set on/off + it->second->saveInfo(info); + // maybe it is useful to update flags with real status. I do not know + /* + if (!(cit->flags & ToolbarBackend::AUTO)) { + unsigned int flags = static_cast(cit->flags); + flags &= ~(info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarBackend::OFF : ToolbarBackend::ON); + flags |= (info.state == ToolbarSection::ToolbarInfo::ON ? ToolbarBackend::ON : ToolbarBackend::OFF); + if (info.state == ToolbarSection::ToolbarInfo::ON) + cit->flags = static_cast(flags); + } + */ + } +} + + void Toolbars::setLayout(string const & layout) { if (layout_) diff --git a/src/frontends/Toolbars.h b/src/frontends/Toolbars.h index 4ea55274e5..8f65f29b8d 100644 --- a/src/frontends/Toolbars.h +++ b/src/frontends/Toolbars.h @@ -26,6 +26,7 @@ #include "ToolbarBackend.h" #include #include +#include "session.h" namespace lyx { @@ -64,6 +65,10 @@ public: * metrics should be updated. */ virtual void show(bool update_metrics) = 0; + /** update toolbar information + * ToolbarInfo will then be saved by session + */ + virtual void saveInfo(ToolbarSection::ToolbarInfo & info) = 0; /// Refresh the contents of the bar. virtual void update() = 0; @@ -83,9 +88,15 @@ public: /// Show/hide the named toolbar. void display(std::string const & name, bool show); + /// toggle the state of toolbars (on/off/auto) + void toggleToolbarState(std::string const & name); + /// Update the state of the toolbars. void update(bool in_math, bool in_table, bool review); + /// save toolbar information + void saveToolbarInfo(); + /// Select the right layout in the combox. void setLayout(std::string const & layout); @@ -128,6 +139,9 @@ private: /// The last textclass layout list in the layout choice selector int last_textclass_; + + // load flags with saved values + void initFlags(ToolbarBackend::Toolbar & tbb); }; /// Set the layout in the kernel when an entry has been selected diff --git a/src/frontends/qt4/GuiView.C b/src/frontends/qt4/GuiView.C index 0bdc5bfa5c..fd9f1f44f4 100644 --- a/src/frontends/qt4/GuiView.C +++ b/src/frontends/qt4/GuiView.C @@ -185,6 +185,7 @@ void GuiView::saveGeometry() session.sessionInfo().save("WindowPosX", convert(geometry.x())); session.sessionInfo().save("WindowPosY", convert(geometry.y())); } + getToolbars().saveToolbarInfo(); } void GuiView::setGeometry(unsigned int width, diff --git a/src/frontends/qt4/QLToolbar.C b/src/frontends/qt4/QLToolbar.C index 536f177bb2..a8a8461e34 100644 --- a/src/frontends/qt4/QLToolbar.C +++ b/src/frontends/qt4/QLToolbar.C @@ -214,6 +214,32 @@ void QLToolbar::show(bool) } +void QLToolbar::saveInfo(ToolbarSection::ToolbarInfo & info) +{ + // if info.state == auto *do not* set on/off + if (info.state != ToolbarSection::ToolbarInfo::AUTO) { + if (QLToolbar::isVisible()) + info.state = ToolbarSection::ToolbarInfo::ON; + else + info.state = ToolbarSection::ToolbarInfo::OFF; + } + // + // no need to save it here. + Qt::ToolBarArea loc = owner_.toolBarArea(this); + + if (loc == Qt::TopToolBarArea) + info.location = ToolbarSection::ToolbarInfo::TOP; + else if (loc == Qt::BottomToolBarArea) + info.location = ToolbarSection::ToolbarInfo::BOTTOM; + else if (loc == Qt::RightToolBarArea) + info.location = ToolbarSection::ToolbarInfo::RIGHT; + else if (loc == Qt::LeftToolBarArea) + info.location = ToolbarSection::ToolbarInfo::LEFT; + else + info.location = ToolbarSection::ToolbarInfo::NOTSET; +} + + void QLToolbar::update() { // This is a speed bottleneck because this is called on every keypress diff --git a/src/frontends/qt4/QLToolbar.h b/src/frontends/qt4/QLToolbar.h index b09b238a4c..9edb0f1924 100644 --- a/src/frontends/qt4/QLToolbar.h +++ b/src/frontends/qt4/QLToolbar.h @@ -21,6 +21,7 @@ #include #include +#include "session.h" class QComboBox; @@ -67,6 +68,7 @@ public: void add(FuncRequest const & func, lyx::docstring const & tooltip); void hide(bool); void show(bool); + void saveInfo(ToolbarSection::ToolbarInfo & info); void update(); LayoutBox * layout() const { return layout_.get(); } diff --git a/src/lfuns.h b/src/lfuns.h index 36f579e358..f2baf18079 100644 --- a/src/lfuns.h +++ b/src/lfuns.h @@ -374,6 +374,7 @@ enum kb_action { LFUN_UNICODE_INSERT, // Lgb 20061022 // 285 LFUN_BOOKMARK_CLEAR, // bpeng 20061031 + LFUN_TOOLBAR_TOGGLE_STATE, // bpeng 20061101 LFUN_LASTACTION // end of the table }; diff --git a/src/lyxfunc.C b/src/lyxfunc.C index b290a637a0..cefad6372d 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -635,6 +635,7 @@ FuncStatus LyXFunc::getStatus(FuncRequest const & cmd) const case LFUN_BUFFER_PREVIOUS: case LFUN_WINDOW_NEW: case LFUN_WINDOW_CLOSE: + case LFUN_TOOLBAR_TOGGLE_STATE: // these are handled in our dispatch() break; @@ -1690,6 +1691,10 @@ void LyXFunc::dispatch(FuncRequest const & cmd) LyX::ref().session().bookmarks().clear(); break; + case LFUN_TOOLBAR_TOGGLE_STATE: + lyx_view_->toggleToolbarState(argument); + break; + default: { BOOST_ASSERT(lyx_view_); view()->cursor().dispatch(cmd); diff --git a/src/session.C b/src/session.C index 25cf8cc407..4372d610e8 100644 --- a/src/session.C +++ b/src/session.C @@ -48,6 +48,7 @@ string const sec_lastfilepos = "[cursor positions]"; string const sec_lastopened = "[last opened files]"; string const sec_bookmarks = "[bookmarks]"; string const sec_session = "[session info]"; +string const sec_toolbars = "[toolbars]"; } // anon namespace @@ -267,6 +268,51 @@ BookmarksSection::Bookmark const & BookmarksSection::bookmark(unsigned int i) co } +void ToolbarSection::read(istream & is) +{ + string tmp; + do { + char c = is.peek(); + if (c == '[') + break; + getline(is, tmp); + + // Read session info, saved as key/value pairs + // would better yell if pos returns npos + string::size_type pos = tmp.find_first_of(" = "); + // silently ignore lines without " = " + if (pos != string::npos) { + string key = tmp.substr(0, pos); + int state; + int location; + istringstream value(tmp.substr(pos + 3)); + value >> state; + value.ignore(1); // ignore " " + value >> location; + toolbars[key] = ToolbarInfo(state, location); + } + } while (is.good()); +} + + +void ToolbarSection::write(ostream & os) const +{ + os << '\n' << sec_toolbars << '\n'; + for (ToolbarMap::const_iterator tb = toolbars.begin(); + tb != toolbars.end(); ++tb) { + os << tb->first << " = " + << static_cast(tb->second.state) << " " + << static_cast(tb->second.location) << '\n'; + } +} + + +ToolbarSection::ToolbarInfo & ToolbarSection::load(string const & name) +{ + return toolbars[name]; +} + + void SessionInfoSection::read(istream & is) { string tmp; @@ -349,6 +395,8 @@ void Session::readFile() lastFilePos().read(is); else if (tmp == sec_bookmarks) bookmarks().read(is); + else if (tmp == sec_toolbars) + toolbars().read(is); else if (tmp == sec_session) sessionInfo().read(is); else @@ -368,6 +416,7 @@ void Session::writeFile() const lastOpened().write(os); lastFilePos().write(os); bookmarks().write(os); + toolbars().write(os); sessionInfo().write(os); } else lyxerr << "LyX: Warning: unable to save Session: " diff --git a/src/session.h b/src/session.h index 36c78f57c5..f682e1e450 100644 --- a/src/session.h +++ b/src/session.h @@ -238,6 +238,65 @@ private: }; +class ToolbarSection : SessionSection +{ +public: + /// information about a toolbar, not all information can be + /// saved/restored by all frontends, but this class provides + /// a superset of things that can be managed by session. + class ToolbarInfo + { + public: + /// + ToolbarInfo() : + state(ON), location(NOTSET) { } + /// + ToolbarInfo(int s, int loc) : + state(static_cast(s)), location(static_cast(loc)) { } + + public: + enum State { + ON, + OFF, + AUTO + }; + + /// on/off/auto + State state; + + /// location: this can be intepreted differently. + enum Location { + TOP, + BOTTOM, + LEFT, + RIGHT, + NOTSET + }; + + Location location; + + /// potentially, icons + }; + + /// info for each toolbar + typedef std::map ToolbarMap; + +public: + /// + void read(std::istream & is); + + /// + void write(std::ostream & os) const; + + /// return reference to toolbar info, create a new one if needed + ToolbarInfo & load(std::string const & name); + +private: + /// toolbar information + ToolbarMap toolbars; +}; + + class SessionInfoSection : SessionSection { public: @@ -306,6 +365,12 @@ public: /// BookmarksSection const & bookmarks() const { return bookmarks_; } + /// + ToolbarSection & toolbars() { return toolbars_; } + + /// + ToolbarSection const & toolbars() const { return toolbars_; } + /// SessionInfoSection & sessionInfo() { return session_info; } @@ -335,6 +400,9 @@ private: /// BookmarksSection bookmarks_; + /// + ToolbarSection toolbars_; + /// SessionInfoSection session_info; }; -- 2.39.5