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.


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@28250 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Vincent van Ravesteijn 2009-01-18 21:50:23 +00:00
parent 53064b49e8
commit cf40884454
4 changed files with 226 additions and 59 deletions

View File

@ -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
@ -301,8 +302,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<std::string>(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
@ -333,6 +390,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);
}
@ -349,6 +409,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: "

View File

@ -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 {
@ -263,11 +264,59 @@ private:
};
class LastCommandsSection : SessionSection
{
public:
///
typedef std::vector<std::string> 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;
///
@ -286,6 +335,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;
@ -311,6 +364,8 @@ private:
LastFilePosSection last_file_pos;
///
BookmarksSection bookmarks_;
///
LastCommandsSection last_commands;
};
/// This is a singleton class. Get the instance.

View File

@ -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()) {
bool event(QEvent * ev) {
if (ev->type() == QEvent::MouseButtonPress) {
QMouseEvent * me = static_cast<QMouseEvent *>(ev);
if (me->x() < 0 || me->y() < 0
|| me->x() > width() || me->y() > height())
hide();
} else {
// emit signal
itemPressed(currentItem());
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,46 +174,50 @@ void GuiCommandBuffer::complete()
string new_input;
vector<string> comp = completions(input, new_input);
if (comp.empty() && new_input == input) {
// show_info_suffix(qt_("[no match]"), input);
return;
}
if (comp.empty()) {
if (new_input != input)
edit_->setText(toqstr(new_input));
// show_info_suffix(("[only completion]"), 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<string> 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<string>::const_iterator cit = comp.begin();
vector<string>::const_iterator end = comp.end();
vector<string>::const_iterator cit = list.begin();
vector<string>::const_iterator end = list.end();
if (!reversed) {
for (; cit != end; ++cit)
list->addItem(toqstr(*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<QWidget const *>(sender());
const_cast<QWidget *>(widget)->hide();
@ -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,11 +245,11 @@ 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());
}
@ -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_);

View File

@ -16,6 +16,7 @@
#include "support/docstring.h"
#include <QPushButton>
#include <QWidget>
#include <vector>
@ -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<std::string> const & list,
QPoint const & pos, bool reversed = false) const;
/// return the possible completions
std::vector<std::string> const completions(std::string const & prefix,
std::string & new_prefix);
@ -82,6 +90,12 @@ private:
/// current position in command history
std::vector<std::string>::const_iterator history_pos_;
/// the button up
QPushButton * upPB;
/// the button down
QPushButton * downPB;
};
} // namespace frontend