From 0f93daf6a3ae9e7a2164868e413e9981417a3438 Mon Sep 17 00:00:00 2001 From: Vincent van Ravesteijn Date: Sun, 15 Mar 2009 13:31:37 +0000 Subject: [PATCH] branch: UI Command Buffer improvements. * the history is stored in the session file and restored in the next LyX session, * the lists now disappear when the mouse is released in stead of pressed, * correct enabling/disabling of the up/down button, * hide the lists when clicked outside the list. Now using the function event() and check for a mouseButtonPressEvent instead of using mouseReleaseEvent(). The latter is only called when the mouse button is released inside the widget, but we want to use this event to detect a mouseclick outside the list. see: http://www.lyx.org/trac/changeset/28250 http://www.lyx.org/trac/changeset/28794 git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_6_X@28796 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/Session.cpp | 65 ++++++++++- src/Session.h | 57 +++++++++- src/frontends/qt4/GuiCommandBuffer.cpp | 145 ++++++++++++++++--------- src/frontends/qt4/GuiCommandBuffer.h | 18 ++- status.16x | 3 +- 5 files changed, 228 insertions(+), 60 deletions(-) diff --git a/src/Session.cpp b/src/Session.cpp index f09d2f6b73..b7ddffc8f8 100644 --- a/src/Session.cpp +++ b/src/Session.cpp @@ -33,6 +33,7 @@ string const sec_lastopened = "[last opened files]"; string const sec_bookmarks = "[bookmarks]"; string const sec_session = "[session info]"; string const sec_toolbars = "[toolbars]"; +string const sec_lastcommands = "[last commands]"; } // anon namespace @@ -291,8 +292,64 @@ BookmarksSection::Bookmark const & BookmarksSection::bookmark(unsigned int i) co } -Session::Session(unsigned int num) : - last_files(num) +LastCommandsSection::LastCommandsSection(unsigned int num) : + default_num_last_commands(30), + absolute_max_last_commands(100) +{ + setNumberOfLastCommands(num); +} + + +void LastCommandsSection::read(istream & is) +{ + string tmp; + do { + char c = is.peek(); + if (c == '[') + break; + getline(is, tmp); + if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ') + continue; + + lastcommands.push_back(tmp); + } while (is.good()); +} + + +void LastCommandsSection::write(ostream & os) const +{ + os << '\n' << sec_lastcommands << '\n'; + copy(lastcommands.begin(), lastcommands.end(), + ostream_iterator(os, "\n")); +} + + +void LastCommandsSection::setNumberOfLastCommands(unsigned int no) +{ + if (0 < no && no <= absolute_max_last_commands) + num_lastcommands = no; + else { + LYXERR(Debug::INIT, "LyX: session: too many last commands\n" + << "\tdefault (=" << default_num_last_commands << ") used."); + num_lastcommands = default_num_last_commands; + } +} + + +void LastCommandsSection::add(std::string const & string) +{ + lastcommands.push_back(string); +} + + +void LastCommandsSection::clear() +{ + lastcommands.clear(); +} + + +Session::Session(unsigned int num_last_files, unsigned int num_last_commands) : + last_files(num_last_files), last_commands(num_last_commands) { // locate the session file // note that the session file name 'session' is hard-coded @@ -323,6 +380,9 @@ void Session::readFile() lastFilePos().read(is); else if (tmp == sec_bookmarks) bookmarks().read(is); + else if (tmp == sec_lastcommands) + lastCommands().read(is); + else LYXERR(Debug::INIT, "LyX: Warning: unknown Session section: " << tmp); } @@ -339,6 +399,7 @@ void Session::writeFile() const lastFiles().write(os); lastOpened().write(os); lastFilePos().write(os); + lastCommands().write(os); bookmarks().write(os); } else LYXERR(Debug::INIT, "LyX: Warning: unable to save Session: " diff --git a/src/Session.h b/src/Session.h index d673da22e9..a111bc4f23 100644 --- a/src/Session.h +++ b/src/Session.h @@ -27,6 +27,7 @@ 3. opened files when a lyx session is closed (lastopened) 4. bookmarks 5. general purpose session info in the form of key/value pairs + 6. the latest commands entered in the command buffer (lastcommands) */ namespace lyx { @@ -260,11 +261,59 @@ private: }; +class LastCommandsSection : SessionSection +{ +public: + /// + typedef std::vector LastCommands; + +public: + /// + LastCommandsSection(unsigned int num); + /// + void read(std::istream & is); + + /// + void write(std::ostream & os) const; + + /// Return lastcommands container (vector) + LastCommands const getcommands() const { return lastcommands; } + + /** add command to lastcommands list + @param command command to add + */ + void add(std::string const & command); + + /** clear lastcommands list + */ + void clear(); + +private: + /// number of commands in the lastcommands list. + unsigned int num_lastcommands; + + /** Used by the constructor to set the number of stored last commands. + @param num the number of lastcommands to set. + */ + void setNumberOfLastCommands(unsigned int num); + + /// a list of lastopened commands + LastCommands lastcommands; + + /// Default number of lastcommands. + unsigned int const default_num_last_commands; + + /// Max number of lastcommands. + unsigned int const absolute_max_last_commands; +}; + + class Session { public: /// Read the session file. @param num length of lastfiles - explicit Session(unsigned int num = 4); + explicit Session(unsigned int num_last_files = 4, + unsigned int num_last_commands = 30); /// Write the session file. void writeFile() const; /// @@ -283,6 +332,10 @@ public: BookmarksSection & bookmarks() { return bookmarks_; } /// BookmarksSection const & bookmarks() const { return bookmarks_; } + /// + LastCommandsSection & lastCommands() { return last_commands; } + /// + LastCommandsSection const & lastCommands() const { return last_commands; } private: friend class LyX; @@ -308,6 +361,8 @@ private: LastFilePosSection last_file_pos; /// BookmarksSection bookmarks_; + /// + LastCommandsSection last_commands; }; /// This is a singleton class. Get the instance. diff --git a/src/frontends/qt4/GuiCommandBuffer.cpp b/src/frontends/qt4/GuiCommandBuffer.cpp index 9293e915cb..23388f0ca0 100644 --- a/src/frontends/qt4/GuiCommandBuffer.cpp +++ b/src/frontends/qt4/GuiCommandBuffer.cpp @@ -23,6 +23,7 @@ #include "LyXFunc.h" #include "LyXAction.h" #include "FuncRequest.h" +#include "Session.h" #include "support/lyxalgo.h" #include "support/lstrings.h" @@ -54,14 +55,15 @@ public: setAttribute(Qt::WA_DeleteOnClose); } protected: - void mouseReleaseEvent(QMouseEvent * ev) { - if (ev->x() < 0 || ev->y() < 0 - || ev->x() > width() || ev->y() > height()) { - hide(); - } else { - // emit signal - itemPressed(currentItem()); + bool event(QEvent * ev) { + if (ev->type() == QEvent::MouseButtonPress) { + QMouseEvent * me = static_cast(ev); + if (me->x() < 0 || me->y() < 0 + || me->x() > width() || me->y() > height()) + hide(); + return true; } + return QListWidget::event(ev); } void keyPressEvent(QKeyEvent * ev) { @@ -70,7 +72,7 @@ protected: return; } else if (ev->key() == Qt::Key_Return || ev->key() == Qt::Key_Space) { // emit signal - itemPressed(currentItem()); + itemClicked(currentItem()); } else QListWidget::keyPressEvent(ev); } @@ -80,7 +82,7 @@ protected: GuiCommandBuffer::GuiCommandBuffer(GuiView * view) - : view_(view), history_pos_(history_.end()) + : view_(view) { transform(lyxaction.func_begin(), lyxaction.func_end(), back_inserter(commands_), firster()); @@ -91,13 +93,15 @@ GuiCommandBuffer::GuiCommandBuffer(GuiView * view) QVBoxLayout * top = new QVBoxLayout(this); QHBoxLayout * layout = new QHBoxLayout(0); - QPushButton * up = new QPushButton(qpup, "", this); - up->setMaximumSize(24, 24); - QPushButton * down = new QPushButton(qpdown, "", this); - down->setToolTip(qt_("Next command")); - down->setMaximumSize(24, 24); - connect(down, SIGNAL(clicked()), this, SLOT(down())); - connect(up, SIGNAL(clicked()), this, SLOT(up())); + upPB = new QPushButton(qpup, "", this); + upPB->setToolTip(qt_("List of previous commands")); + upPB->setMaximumSize(24, 24); + downPB = new QPushButton(qpdown, "", this); + downPB->setToolTip(qt_("Next command")); + downPB->setMaximumSize(24, 24); + downPB->setEnabled(false); + connect(downPB, SIGNAL(clicked()), this, SLOT(down())); + connect(upPB, SIGNAL(pressed()), this, SLOT(listHistoryUp())); edit_ = new GuiCommandEdit(this); edit_->setMinimumSize(edit_->sizeHint()); @@ -110,13 +114,26 @@ GuiCommandBuffer::GuiCommandBuffer(GuiView * view) connect(edit_, SIGNAL(downPressed()), this, SLOT(down())); connect(edit_, SIGNAL(hidePressed()), this, SLOT(hideParent())); - layout->addWidget(up, 0); - layout->addWidget(down, 0); + layout->addWidget(upPB, 0); + layout->addWidget(downPB, 0); layout->addWidget(edit_, 10); layout->setMargin(0); top->addLayout(layout); top->setMargin(0); setFocusProxy(edit_); + + LastCommandsSection::LastCommands last_commands + = theSession().lastCommands().getcommands(); + LastCommandsSection::LastCommands::const_iterator it + = last_commands.begin(); + LastCommandsSection::LastCommands::const_iterator end + = last_commands.end(); + + upPB->setEnabled(it != end); + + for(; it != end; ++it) + history_.push_back(*it); + history_pos_ = history_.end(); } @@ -133,7 +150,21 @@ void GuiCommandBuffer::dispatch() view_->setFocus(); edit_->setText(QString()); edit_->clearFocus(); - dispatch(fromqstr(cmd)); + std::string const cmd_ = fromqstr(cmd); + theSession().lastCommands().add(cmd_); + dispatch(cmd_); +} + + +void GuiCommandBuffer::listHistoryUp() +{ + if (history_.size()==1) { + edit_->setText(toqstr(history_.back())); + upPB->setEnabled(false); + return; + } + QPoint const & pos = upPB->mapToGlobal(QPoint(0, 0)); + showList(history_, pos, true); } @@ -143,50 +174,54 @@ void GuiCommandBuffer::complete() string new_input; vector comp = completions(input, new_input); - if (comp.empty() && new_input == input) { - // show_info_suffix(qt_("[no match]"), input); - return; - } - if (comp.empty()) { - edit_->setText(toqstr(new_input)); - // show_info_suffix(("[only completion]"), new_input + ' '); + if (new_input != input) + edit_->setText(toqstr(new_input)); return; } edit_->setText(toqstr(new_input)); + QPoint const & pos = edit_->mapToGlobal(QPoint(0, 0)); + showList(comp, pos); +} - QTempListBox * list = new QTempListBox; +void GuiCommandBuffer::showList(vector const & list, + QPoint const & pos, bool reversed) const +{ + QTempListBox * listBox = new QTempListBox; // For some reason the scrollview's contents are larger // than the number of actual items... - vector::const_iterator cit = comp.begin(); - vector::const_iterator end = comp.end(); - for (; cit != end; ++cit) - list->addItem(toqstr(*cit)); + vector::const_iterator cit = list.begin(); + vector::const_iterator end = list.end(); + if (!reversed) { + for (; cit != end; ++cit) + listBox ->addItem(toqstr(*cit)); + } else { + for (--end; end != cit; --end) + listBox ->addItem(toqstr(*end)); + } - list->resize(list->sizeHint()); - QPoint const pos = edit_->mapToGlobal(QPoint(0, 0)); + listBox->resize(listBox ->sizeHint()); - int const y = max(0, pos.y() - list->height()); + int const y = max(0, pos.y() - listBox->height()); + listBox->move(pos.x(), y); - list->move(pos.x(), y); + connect(listBox, SIGNAL(itemClicked(QListWidgetItem *)), + this, SLOT(item_selected(QListWidgetItem *))); + connect(listBox, SIGNAL(itemActivated(QListWidgetItem *)), + this, SLOT(item_selected(QListWidgetItem *))); - connect(list, SIGNAL(itemPressed(QListWidgetItem *)), - this, SLOT(complete_selected(QListWidgetItem *))); - connect(list, SIGNAL(itemActivated(QListWidgetItem *)), - this, SLOT(complete_selected(QListWidgetItem *))); - - list->show(); - list->setFocus(); + listBox->show(); + listBox->setFocus(); } -void GuiCommandBuffer::complete_selected(QListWidgetItem * item) +void GuiCommandBuffer::item_selected(QListWidgetItem * item) { QWidget const * widget = static_cast(sender()); const_cast(widget)->hide(); - edit_->setText(item->text() + ' '); + edit_->setText(item->text()+ ' '); edit_->activateWindow(); edit_->setFocus(); } @@ -197,11 +232,11 @@ void GuiCommandBuffer::up() string const input = fromqstr(edit_->text()); string const h = historyUp(); - if (h.empty()) { - // show_info_suffix(qt_("[Beginning of history]"), input); - } else { + if (!h.empty()) edit_->setText(toqstr(h)); - } + + upPB->setEnabled(history_pos_ != history_.begin()); + downPB->setEnabled(history_pos_ != history_.end()); } @@ -210,13 +245,13 @@ void GuiCommandBuffer::down() string const input = fromqstr(edit_->text()); string const h = historyDown(); - if (h.empty()) { - // show_info_suffix(qt_("[End of history]"), input); - } else { + if (!h.empty()) edit_->setText(toqstr(h)); - } -} + downPB->setEnabled(history_pos_ != history_.end()-1); + upPB->setEnabled(history_pos_ != history_.begin()); +} + void GuiCommandBuffer::hideParent() { @@ -317,8 +352,10 @@ void GuiCommandBuffer::dispatch(string const & str) if (str.empty()) return; - history_.push_back(str); + history_.push_back(trim(str)); history_pos_ = history_.end(); + upPB->setEnabled(history_pos_ != history_.begin()); + downPB->setEnabled(history_pos_ != history_.end()); FuncRequest func = lyxaction.lookupFunc(str); func.origin = FuncRequest::COMMANDBUFFER; theLyXFunc().setLyXView(view_); diff --git a/src/frontends/qt4/GuiCommandBuffer.h b/src/frontends/qt4/GuiCommandBuffer.h index 9f8ec74216..d130e2c68a 100644 --- a/src/frontends/qt4/GuiCommandBuffer.h +++ b/src/frontends/qt4/GuiCommandBuffer.h @@ -16,6 +16,7 @@ #include "support/docstring.h" +#include #include #include @@ -42,8 +43,10 @@ public Q_SLOTS: void dispatch(); /// tab-complete void complete(); - /// select-complete - void complete_selected(QListWidgetItem *); + /// show history + void listHistoryUp(); + /// called when an item in a list is selected + void item_selected(QListWidgetItem *); /// up void up(); /// down @@ -67,6 +70,11 @@ private: /// hide the command buffer. void hide() const; + /// open a listbox and show the contents of the list. When reversed + /// is true, the contents of the list is filled bottom-up. + void showList(std::vector const & list, + QPoint const & pos, bool reversed = false) const; + /// return the possible completions std::vector const completions(std::string const & prefix, std::string & new_prefix); @@ -82,6 +90,12 @@ private: /// current position in command history std::vector::const_iterator history_pos_; + + /// the button up + QPushButton * upPB; + + /// the button down + QPushButton * downPB; }; } // namespace frontend diff --git a/status.16x b/status.16x index fd40e8c1db..eddcb72794 100644 --- a/status.16x +++ b/status.16x @@ -34,7 +34,8 @@ What's new * USER INTERFACE - +- Store the command buffer history in the session file and show it in + a pop-up list in the command buffer. * WINDOWS INSTALLER