mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-26 14:15:32 +00:00
The BufferView/WorkArea/LyXView reorg a.k.a Multiple WorkAreas:
* Buffer: - get rid of cursor_ and anchor_ - ~Buffer(): update the labels of its master buffer before closing - closing(): pass the Buffer address. * BufferView(): - BufferView(): needs a valid Buffer (should be const in the future. - most of the change is about removing all test of buffer_ nullity. - resize(): deleted. - setBuffer(): deleted. * Application: - newLyXView(): simplification - updated design description in Application.h * Gui/GuiImplementation: remove all WorkAreas and BufferView creation/Deletion. Workareas are directly handled by LyXView/GuiView and BufferView is created/delete by WorkArea. * LyXView/GuiView: implement the new design What is not working yet: - the close tab button: it is implemented but does not show up. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@19686 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
7206f23872
commit
1356543c45
@ -22,6 +22,7 @@
|
||||
#include "Bullet.h"
|
||||
#include "Chktex.h"
|
||||
#include "debug.h"
|
||||
#include "DocIterator.h"
|
||||
#include "Encoding.h"
|
||||
#include "ErrorList.h"
|
||||
#include "Exporter.h"
|
||||
@ -227,7 +228,12 @@ Buffer::~Buffer()
|
||||
// here the buffer should take care that it is
|
||||
// saved properly, before it goes into the void.
|
||||
|
||||
closing();
|
||||
Buffer * master = getMasterBuffer();
|
||||
if (master != this && use_gui)
|
||||
// We are closing buf which was a child document so we
|
||||
// must update the labels and section numbering of its master
|
||||
// Buffer.
|
||||
updateLabels(*master);
|
||||
|
||||
if (!temppath().empty() && !destroyDir(FileName(temppath()))) {
|
||||
Alert::warning(_("Could not remove temporary directory"),
|
||||
@ -237,6 +243,8 @@ Buffer::~Buffer()
|
||||
|
||||
// Remove any previewed LaTeX snippets associated with this buffer.
|
||||
graphics::Previews::get().removeLoader(*this);
|
||||
|
||||
closing(this);
|
||||
}
|
||||
|
||||
|
||||
@ -1707,13 +1715,6 @@ void Buffer::buildMacros()
|
||||
}
|
||||
|
||||
|
||||
void Buffer::saveCursor(StableDocIterator cur, StableDocIterator anc)
|
||||
{
|
||||
cursor_ = cur;
|
||||
anchor_ = anc;
|
||||
}
|
||||
|
||||
|
||||
void Buffer::changeRefsIfUnique(docstring const & from, docstring const & to,
|
||||
Inset::Code code)
|
||||
{
|
||||
|
15
src/Buffer.h
15
src/Buffer.h
@ -25,7 +25,6 @@
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@ -50,7 +49,6 @@ class OutputParams;
|
||||
class ParConstIterator;
|
||||
class ParIterator;
|
||||
class ParagraphList;
|
||||
class StableDocIterator;
|
||||
class TeXErrors;
|
||||
class TexRow;
|
||||
class TocBackend;
|
||||
@ -159,7 +157,7 @@ public:
|
||||
/// Reset autosave timers for all users.
|
||||
boost::signal<void()> resetAutosaveTimers;
|
||||
/// This signal is emitting if the buffer is being closed.
|
||||
boost::signal<void()> closing;
|
||||
boost::signal<void(Buffer *)> closing;
|
||||
|
||||
|
||||
/** Save file.
|
||||
@ -381,12 +379,6 @@ public:
|
||||
///
|
||||
void insertMacro(docstring const & name, MacroData const & data);
|
||||
|
||||
///
|
||||
void saveCursor(StableDocIterator cursor, StableDocIterator anchor);
|
||||
///
|
||||
StableDocIterator getCursor() const { return cursor_; }
|
||||
///
|
||||
StableDocIterator getAnchor() const { return anchor_; }
|
||||
///
|
||||
void changeRefsIfUnique(docstring const & from, docstring const & to,
|
||||
Inset::Code code);
|
||||
@ -417,11 +409,6 @@ private:
|
||||
/// The pointer never changes although *pimpl_'s contents may.
|
||||
boost::scoped_ptr<Impl> const pimpl_;
|
||||
|
||||
/// Save the cursor Position on Buffer switch
|
||||
/// this would not be needed if every Buffer would have
|
||||
/// it's BufferView, this should be FIXED in future.
|
||||
StableDocIterator cursor_;
|
||||
StableDocIterator anchor_;
|
||||
/// A cache for the bibfiles (including bibfiles of loaded child
|
||||
/// documents), needed for appropriate update of natbib labels.
|
||||
mutable std::vector<support::FileName> bibfilesCache_;
|
||||
|
@ -122,14 +122,21 @@ T * getInsetByCode(Cursor & cur, Inset::Code code)
|
||||
} // anon namespace
|
||||
|
||||
|
||||
BufferView::BufferView()
|
||||
: width_(0), height_(0), buffer_(0), wh_(0),
|
||||
BufferView::BufferView(Buffer & buf)
|
||||
: width_(0), height_(0), buffer_(buf), wh_(0),
|
||||
cursor_(*this),
|
||||
multiparsel_cache_(false), anchor_ref_(0), offset_ref_(0),
|
||||
intl_(new Intl), last_inset_(0)
|
||||
{
|
||||
xsel_cache_.set = false;
|
||||
intl_->initKeyMapper(lyxrc.use_kbmap);
|
||||
|
||||
cursor_.push(buffer_.inset());
|
||||
cursor_.resetAnchor();
|
||||
buffer_.text().setCurrentFont(cursor_);
|
||||
|
||||
if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
|
||||
graphics::Previews::get().generateBufferPreviews(buffer_);
|
||||
}
|
||||
|
||||
|
||||
@ -138,124 +145,15 @@ BufferView::~BufferView()
|
||||
}
|
||||
|
||||
|
||||
Buffer * BufferView::buffer() const
|
||||
Buffer * BufferView::buffer()
|
||||
{
|
||||
return buffer_;
|
||||
return &buffer_;
|
||||
}
|
||||
|
||||
|
||||
Buffer * BufferView::setBuffer(Buffer * b)
|
||||
Buffer const * BufferView::buffer() const
|
||||
{
|
||||
LYXERR(Debug::INFO) << BOOST_CURRENT_FUNCTION
|
||||
<< "[ b = " << b << "]" << endl;
|
||||
|
||||
if (buffer_) {
|
||||
// Save the current selection if any
|
||||
cap::saveSelection(cursor_);
|
||||
// Save the actual cursor position and anchor inside the
|
||||
// buffer so that it can be restored in case we rechange
|
||||
// to this buffer later on.
|
||||
buffer_->saveCursor(cursor_.selectionBegin(),
|
||||
cursor_.selectionEnd());
|
||||
// update bookmark pit of the current buffer before switch
|
||||
for (size_t i = 0; i < LyX::ref().session().bookmarks().size(); ++i) {
|
||||
BookmarksSection::Bookmark const & bm = LyX::ref().session().bookmarks().bookmark(i);
|
||||
if (buffer()->fileName() != bm.filename.absFilename())
|
||||
continue;
|
||||
// if top_id or bottom_pit, bottom_pos has been changed, update bookmark
|
||||
// see http://bugzilla.lyx.org/show_bug.cgi?id=3092
|
||||
pit_type new_pit;
|
||||
pos_type new_pos;
|
||||
int new_id;
|
||||
boost::tie(new_pit, new_pos, new_id) = moveToPosition(bm.bottom_pit, bm.bottom_pos, bm.top_id, bm.top_pos);
|
||||
if (bm.bottom_pit != new_pit || bm.bottom_pos != new_pos || bm.top_id != new_id )
|
||||
const_cast<BookmarksSection::Bookmark &>(bm).updatePos(new_pit, new_pos, new_id);
|
||||
}
|
||||
// current buffer is going to be switched-off, save cursor pos
|
||||
// Ideally, the whole cursor stack should be saved, but session
|
||||
// currently can only handle bottom (whole document) level pit and pos.
|
||||
// That is to say, if a cursor is in a nested inset, it will be
|
||||
// restore to the left of the top level inset.
|
||||
LyX::ref().session().lastFilePos().save(FileName(buffer_->fileName()),
|
||||
boost::tie(cursor_.bottom().pit(), cursor_.bottom().pos()) );
|
||||
}
|
||||
|
||||
// If we're quitting lyx, don't bother updating stuff
|
||||
if (quitting) {
|
||||
buffer_ = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//FIXME Fix for bug 3440 is here.
|
||||
// If we are closing current buffer, switch to the first in
|
||||
// buffer list.
|
||||
if (!b) {
|
||||
LYXERR(Debug::INFO) << BOOST_CURRENT_FUNCTION
|
||||
<< " No Buffer!" << endl;
|
||||
// We are closing the buffer, use the first buffer as current
|
||||
//FIXME 3440
|
||||
// if (last_buffer_) buffer_ = last_buffer_;
|
||||
// also check that this is in theBufferList()?
|
||||
buffer_ = theBufferList().first();
|
||||
} else {
|
||||
//FIXME 3440
|
||||
// last_buffer = buffer_;
|
||||
// Set current buffer
|
||||
buffer_ = b;
|
||||
}
|
||||
|
||||
// Reset old cursor
|
||||
cursor_ = Cursor(*this);
|
||||
anchor_ref_ = 0;
|
||||
offset_ref_ = 0;
|
||||
|
||||
if (!buffer_)
|
||||
return 0;
|
||||
|
||||
LYXERR(Debug::INFO) << BOOST_CURRENT_FUNCTION
|
||||
<< "Buffer addr: " << buffer_ << endl;
|
||||
cursor_.push(buffer_->inset());
|
||||
cursor_.resetAnchor();
|
||||
buffer_->text().setCurrentFont(cursor_);
|
||||
|
||||
// Update the metrics now that we have a proper Cursor.
|
||||
updateMetrics(false);
|
||||
|
||||
// FIXME: This code won't be needed once we switch to
|
||||
// "one Buffer" / "one BufferView".
|
||||
if (buffer_->getCursor().size() > 0 &&
|
||||
buffer_->getAnchor().size() > 0)
|
||||
{
|
||||
cursor_.setCursor(buffer_->getAnchor().asDocIterator(&(buffer_->inset())));
|
||||
cursor_.resetAnchor();
|
||||
cursor_.setCursor(buffer_->getCursor().asDocIterator(&(buffer_->inset())));
|
||||
cursor_.setSelection();
|
||||
// do not set selection to the new buffer because we
|
||||
// only paste recent selection.
|
||||
|
||||
// Make sure that the restored cursor is not broken. This can happen for
|
||||
// example if this Buffer has been modified by another view.
|
||||
cursor_.fixIfBroken();
|
||||
|
||||
if (fitCursor())
|
||||
// Update the metrics if the cursor new position was off screen.
|
||||
updateMetrics(false);
|
||||
}
|
||||
|
||||
if (graphics::Previews::status() != LyXRC::PREVIEW_OFF)
|
||||
graphics::Previews::get().generateBufferPreviews(*buffer_);
|
||||
return buffer_;
|
||||
}
|
||||
|
||||
|
||||
void BufferView::resize()
|
||||
{
|
||||
if (!buffer_)
|
||||
return;
|
||||
|
||||
LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION << endl;
|
||||
|
||||
updateMetrics(false);
|
||||
return &buffer_;
|
||||
}
|
||||
|
||||
|
||||
@ -298,17 +196,11 @@ bool BufferView::update(Update::flags flags)
|
||||
<< "[fitcursor = " << (flags & Update::FitCursor)
|
||||
<< ", forceupdate = " << (flags & Update::Force)
|
||||
<< ", singlepar = " << (flags & Update::SinglePar)
|
||||
<< "] buffer: " << buffer_ << endl;
|
||||
|
||||
// Check needed to survive LyX startup
|
||||
if (!buffer_)
|
||||
return false;
|
||||
|
||||
LYXERR(Debug::WORKAREA) << "BufferView::update" << std::endl;
|
||||
<< "] buffer: " << &buffer_ << endl;
|
||||
|
||||
// Update macro store
|
||||
if (!(cursor().inMathed() && cursor().inMacroMode()))
|
||||
buffer_->buildMacros();
|
||||
buffer_.buildMacros();
|
||||
|
||||
// Now do the first drawing step if needed. This consists on updating
|
||||
// the CoordCache in updateMetrics().
|
||||
@ -360,14 +252,7 @@ bool BufferView::update(Update::flags flags)
|
||||
|
||||
void BufferView::updateScrollbar()
|
||||
{
|
||||
if (!buffer_) {
|
||||
LYXERR(Debug::DEBUG) << BOOST_CURRENT_FUNCTION
|
||||
<< " no text in updateScrollbar" << endl;
|
||||
scrollbarParameters_.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
Text & t = buffer_->text();
|
||||
Text & t = buffer_.text();
|
||||
TextMetrics & tm = text_metrics_[&t];
|
||||
|
||||
int const parsize = int(t.paragraphs().size() - 1);
|
||||
@ -432,10 +317,7 @@ void BufferView::scrollDocView(int value)
|
||||
LYXERR(Debug::GUI) << BOOST_CURRENT_FUNCTION
|
||||
<< "[ value = " << value << "]" << endl;
|
||||
|
||||
if (!buffer_)
|
||||
return;
|
||||
|
||||
Text & t = buffer_->text();
|
||||
Text & t = buffer_.text();
|
||||
TextMetrics & tm = text_metrics_[&t];
|
||||
|
||||
float const bar = value / float(wh_ * t.paragraphs().size());
|
||||
@ -453,10 +335,7 @@ void BufferView::scrollDocView(int value)
|
||||
|
||||
void BufferView::setCursorFromScrollbar()
|
||||
{
|
||||
if (!buffer_)
|
||||
return;
|
||||
|
||||
Text & t = buffer_->text();
|
||||
Text & t = buffer_.text();
|
||||
|
||||
int const height = 2 * defaultRowHeight();
|
||||
int const first = height;
|
||||
@ -469,14 +348,14 @@ void BufferView::setCursorFromScrollbar()
|
||||
case bv_funcs::CUR_ABOVE:
|
||||
// We reset the cursor because bv_funcs::status() does not
|
||||
// work when the cursor is within mathed.
|
||||
cur.reset(buffer_->inset());
|
||||
cur.reset(buffer_.inset());
|
||||
t.setCursorFromCoordinates(cur, 0, first);
|
||||
cur.clearSelection();
|
||||
break;
|
||||
case bv_funcs::CUR_BELOW:
|
||||
// We reset the cursor because bv_funcs::status() does not
|
||||
// work when the cursor is within mathed.
|
||||
cur.reset(buffer_->inset());
|
||||
cur.reset(buffer_.inset());
|
||||
t.setCursorFromCoordinates(cur, 0, last);
|
||||
cur.clearSelection();
|
||||
break;
|
||||
@ -484,7 +363,7 @@ void BufferView::setCursorFromScrollbar()
|
||||
int const y = bv_funcs::getPos(*this, cur, cur.boundary()).y_;
|
||||
int const newy = min(last, max(y, first));
|
||||
if (y != newy) {
|
||||
cur.reset(buffer_->inset());
|
||||
cur.reset(buffer_.inset());
|
||||
t.setCursorFromCoordinates(cur, 0, newy);
|
||||
}
|
||||
}
|
||||
@ -508,7 +387,7 @@ void BufferView::saveBookmark(unsigned int idx)
|
||||
// pit and pos will be updated with bottom level pit/pos
|
||||
// when lyx exits.
|
||||
LyX::ref().session().bookmarks().save(
|
||||
FileName(buffer_->fileName()),
|
||||
FileName(buffer_.fileName()),
|
||||
cursor_.bottom().pit(),
|
||||
cursor_.bottom().pos(),
|
||||
cursor_.paragraph().id(),
|
||||
@ -530,8 +409,8 @@ boost::tuple<pit_type, pos_type, int> BufferView::moveToPosition(pit_type bottom
|
||||
// This is the case for a 'live' bookmark when unique paragraph ID
|
||||
// is used to track bookmarks.
|
||||
if (top_id > 0) {
|
||||
ParIterator par = buffer_->getParFromID(top_id);
|
||||
if (par != buffer_->par_iterator_end()) {
|
||||
ParIterator par = buffer_.getParFromID(top_id);
|
||||
if (par != buffer_.par_iterator_end()) {
|
||||
DocIterator dit = makeDocIterator(par, min(par->size(), top_pos));
|
||||
// Some slices of the iterator may not be
|
||||
// reachable (e.g. closed collapsable inset)
|
||||
@ -556,8 +435,8 @@ boost::tuple<pit_type, pos_type, int> BufferView::moveToPosition(pit_type bottom
|
||||
// restoration is inaccurate. If a bookmark was within an inset,
|
||||
// it will be restored to the left of the outmost inset that contains
|
||||
// the bookmark.
|
||||
if (static_cast<size_t>(bottom_pit) < buffer_->paragraphs().size()) {
|
||||
DocIterator it = doc_iterator_begin(buffer_->inset());
|
||||
if (static_cast<size_t>(bottom_pit) < buffer_.paragraphs().size()) {
|
||||
DocIterator it = doc_iterator_begin(buffer_.inset());
|
||||
it.pit() = bottom_pit;
|
||||
it.pos() = min(bottom_pos, it.paragraph().size());
|
||||
setCursor(it);
|
||||
@ -613,10 +492,10 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
|
||||
switch (cmd.action) {
|
||||
|
||||
case LFUN_UNDO:
|
||||
flag.enabled(!buffer_->undostack().empty());
|
||||
flag.enabled(!buffer_.undostack().empty());
|
||||
break;
|
||||
case LFUN_REDO:
|
||||
flag.enabled(!buffer_->redostack().empty());
|
||||
flag.enabled(!buffer_.redostack().empty());
|
||||
break;
|
||||
case LFUN_FILE_INSERT:
|
||||
case LFUN_FILE_INSERT_PLAINTEXT_PARA:
|
||||
@ -656,12 +535,12 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
|
||||
|
||||
case LFUN_CHANGES_TRACK:
|
||||
flag.enabled(true);
|
||||
flag.setOnOff(buffer_->params().trackChanges);
|
||||
flag.setOnOff(buffer_.params().trackChanges);
|
||||
break;
|
||||
|
||||
case LFUN_CHANGES_OUTPUT:
|
||||
flag.enabled(buffer_);
|
||||
flag.setOnOff(buffer_->params().outputChanges);
|
||||
flag.enabled(true);
|
||||
flag.setOnOff(buffer_.params().outputChanges);
|
||||
break;
|
||||
|
||||
case LFUN_CHANGES_MERGE:
|
||||
@ -672,11 +551,11 @@ FuncStatus BufferView::getStatus(FuncRequest const & cmd)
|
||||
// In principle, these command should only be enabled if there
|
||||
// is a change in the document. However, without proper
|
||||
// optimizations, this will inevitably result in poor performance.
|
||||
flag.enabled(buffer_);
|
||||
flag.enabled(true);
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_TOGGLE_COMPRESSION: {
|
||||
flag.setOnOff(buffer_->params().compressed);
|
||||
flag.setOnOff(buffer_.params().compressed);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -702,10 +581,6 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
<< " button[" << cmd.button() << ']'
|
||||
<< endl;
|
||||
|
||||
// FIXME: this should not be possible.
|
||||
if (!buffer_)
|
||||
return Update::None;
|
||||
|
||||
Cursor & cur = cursor_;
|
||||
// Default Update flags.
|
||||
Update::flags updateFlags = Update::Force | Update::FitCursor;
|
||||
@ -774,7 +649,9 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
case LFUN_PARAGRAPH_GOTO: {
|
||||
int const id = convert<int>(to_utf8(cmd.argument()));
|
||||
int i = 0;
|
||||
for (Buffer * b = buffer_; i == 0 || b != buffer_; b = theBufferList().next(b)) {
|
||||
for (Buffer * b = &buffer_; i == 0 || b != &buffer_;
|
||||
b = theBufferList().next(b)) {
|
||||
|
||||
ParIterator par = b->getParFromID(id);
|
||||
if (par == b->par_iterator_end()) {
|
||||
LYXERR(Debug::INFO)
|
||||
@ -786,7 +663,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
<< " found in buffer `"
|
||||
<< b->fileName() << "'." << endl;
|
||||
|
||||
if (b == buffer_) {
|
||||
if (b == &buffer_) {
|
||||
// Set the cursor
|
||||
setCursor(makeDocIterator(par, 0));
|
||||
} else {
|
||||
@ -806,20 +683,20 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
case LFUN_OUTLINE_UP:
|
||||
toc::outline(toc::Up, cursor_);
|
||||
cursor_.text()->setCursor(cursor_, cursor_.pit(), 0);
|
||||
updateLabels(*buffer_);
|
||||
updateLabels(buffer_);
|
||||
break;
|
||||
case LFUN_OUTLINE_DOWN:
|
||||
toc::outline(toc::Down, cursor_);
|
||||
cursor_.text()->setCursor(cursor_, cursor_.pit(), 0);
|
||||
updateLabels(*buffer_);
|
||||
updateLabels(buffer_);
|
||||
break;
|
||||
case LFUN_OUTLINE_IN:
|
||||
toc::outline(toc::In, cursor_);
|
||||
updateLabels(*buffer_);
|
||||
updateLabels(buffer_);
|
||||
break;
|
||||
case LFUN_OUTLINE_OUT:
|
||||
toc::outline(toc::Out, cursor_);
|
||||
updateLabels(*buffer_);
|
||||
updateLabels(buffer_);
|
||||
break;
|
||||
|
||||
case LFUN_NOTE_NEXT:
|
||||
@ -835,12 +712,12 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
}
|
||||
|
||||
case LFUN_CHANGES_TRACK:
|
||||
buffer_->params().trackChanges = !buffer_->params().trackChanges;
|
||||
buffer_.params().trackChanges = !buffer_.params().trackChanges;
|
||||
break;
|
||||
|
||||
case LFUN_CHANGES_OUTPUT:
|
||||
buffer_->params().outputChanges = !buffer_->params().outputChanges;
|
||||
if (buffer_->params().outputChanges) {
|
||||
buffer_.params().outputChanges = !buffer_.params().outputChanges;
|
||||
if (buffer_.params().outputChanges) {
|
||||
bool dvipost = LaTeXFeatures::isAvailable("dvipost");
|
||||
bool xcolorsoul = LaTeXFeatures::isAvailable("soul") &&
|
||||
LaTeXFeatures::isAvailable("xcolor");
|
||||
@ -872,21 +749,21 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
|
||||
case LFUN_ALL_CHANGES_ACCEPT:
|
||||
// select complete document
|
||||
cursor_.reset(buffer_->inset());
|
||||
cursor_.reset(buffer_.inset());
|
||||
cursor_.selHandle(true);
|
||||
buffer_->text().cursorBottom(cursor_);
|
||||
buffer_.text().cursorBottom(cursor_);
|
||||
// accept everything in a single step to support atomic undo
|
||||
buffer_->text().acceptOrRejectChanges(cursor_, Text::ACCEPT);
|
||||
buffer_.text().acceptOrRejectChanges(cursor_, Text::ACCEPT);
|
||||
break;
|
||||
|
||||
case LFUN_ALL_CHANGES_REJECT:
|
||||
// select complete document
|
||||
cursor_.reset(buffer_->inset());
|
||||
cursor_.reset(buffer_.inset());
|
||||
cursor_.selHandle(true);
|
||||
buffer_->text().cursorBottom(cursor_);
|
||||
buffer_.text().cursorBottom(cursor_);
|
||||
// reject everything in a single step to support atomic undo
|
||||
// Note: reject does not work recursively; the user may have to repeat the operation
|
||||
buffer_->text().acceptOrRejectChanges(cursor_, Text::REJECT);
|
||||
buffer_.text().acceptOrRejectChanges(cursor_, Text::REJECT);
|
||||
break;
|
||||
|
||||
case LFUN_WORD_FIND:
|
||||
@ -945,7 +822,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
Inset::BIBTEX_CODE);
|
||||
if (inset) {
|
||||
if (inset->addDatabase(to_utf8(cmd.argument())))
|
||||
buffer_->updateBibfilesCache();
|
||||
buffer_.updateBibfilesCache();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -957,7 +834,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
Inset::BIBTEX_CODE);
|
||||
if (inset) {
|
||||
if (inset->delDatabase(to_utf8(cmd.argument())))
|
||||
buffer_->updateBibfilesCache();
|
||||
buffer_.updateBibfilesCache();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -968,8 +845,8 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
from = cur.selectionBegin();
|
||||
to = cur.selectionEnd();
|
||||
} else {
|
||||
from = doc_iterator_begin(buffer_->inset());
|
||||
to = doc_iterator_end(buffer_->inset());
|
||||
from = doc_iterator_begin(buffer_.inset());
|
||||
to = doc_iterator_end(buffer_.inset());
|
||||
}
|
||||
int const count = countWords(from, to);
|
||||
docstring message;
|
||||
@ -994,7 +871,7 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
|
||||
case LFUN_BUFFER_TOGGLE_COMPRESSION:
|
||||
// turn compression on/off
|
||||
buffer_->params().compressed = !buffer_->params().compressed;
|
||||
buffer_.params().compressed = !buffer_.params().compressed;
|
||||
break;
|
||||
|
||||
case LFUN_NEXT_INSET_TOGGLE: {
|
||||
@ -1031,9 +908,6 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd)
|
||||
|
||||
docstring const BufferView::requestSelection()
|
||||
{
|
||||
if (!buffer_)
|
||||
return docstring();
|
||||
|
||||
Cursor & cur = cursor_;
|
||||
|
||||
if (!cur.selection()) {
|
||||
@ -1056,17 +930,15 @@ docstring const BufferView::requestSelection()
|
||||
|
||||
void BufferView::clearSelection()
|
||||
{
|
||||
if (buffer_) {
|
||||
cursor_.clearSelection();
|
||||
// Clear the selection buffer. Otherwise a subsequent
|
||||
// middle-mouse-button paste would use the selection buffer,
|
||||
// not the more current external selection.
|
||||
cap::clearSelection();
|
||||
xsel_cache_.set = false;
|
||||
// The buffer did not really change, but this causes the
|
||||
// redraw we need because we cleared the selection above.
|
||||
buffer_->changed();
|
||||
}
|
||||
cursor_.clearSelection();
|
||||
// Clear the selection buffer. Otherwise a subsequent
|
||||
// middle-mouse-button paste would use the selection buffer,
|
||||
// not the more current external selection.
|
||||
cap::clearSelection();
|
||||
xsel_cache_.set = false;
|
||||
// The buffer did not really change, but this causes the
|
||||
// redraw we need because we cleared the selection above.
|
||||
buffer_.changed();
|
||||
}
|
||||
|
||||
|
||||
@ -1078,9 +950,7 @@ void BufferView::workAreaResize(int width, int height)
|
||||
|
||||
// The complete text metrics will be redone.
|
||||
text_metrics_.clear();
|
||||
|
||||
if (buffer_)
|
||||
resize();
|
||||
updateMetrics(false);
|
||||
}
|
||||
|
||||
|
||||
@ -1140,12 +1010,8 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
// LFUN_FILE_OPEN generated by drag-and-drop.
|
||||
FuncRequest cmd = cmd0;
|
||||
|
||||
// E.g. Qt mouse press when no buffer
|
||||
if (!buffer_)
|
||||
return false;
|
||||
|
||||
Cursor cur(*this);
|
||||
cur.push(buffer_->inset());
|
||||
cur.push(buffer_.inset());
|
||||
cur.selection() = cursor_.selection();
|
||||
|
||||
// Either the inset under the cursor or the
|
||||
@ -1158,7 +1024,7 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
|
||||
// Get inset under mouse, if there is one.
|
||||
Inset const * covering_inset =
|
||||
getCoveringInset(buffer_->text(), cmd.x, cmd.y);
|
||||
getCoveringInset(buffer_.text(), cmd.x, cmd.y);
|
||||
if (covering_inset == last_inset_)
|
||||
// Same inset, no need to do anything...
|
||||
return false;
|
||||
@ -1208,7 +1074,7 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
}
|
||||
|
||||
// Build temporary cursor.
|
||||
Inset * inset = buffer_->text().editXY(cur, cmd.x, cmd.y);
|
||||
Inset * inset = buffer_.text().editXY(cur, cmd.x, cmd.y);
|
||||
|
||||
// Put anchor at the same position.
|
||||
cur.resetAnchor();
|
||||
@ -1239,10 +1105,7 @@ bool BufferView::workAreaDispatch(FuncRequest const & cmd0)
|
||||
|
||||
void BufferView::scroll(int /*lines*/)
|
||||
{
|
||||
// if (!buffer_)
|
||||
// return;
|
||||
//
|
||||
// Text const * t = &buffer_->text();
|
||||
// Text const * t = buffer_.text();
|
||||
// int const line_height = defaultRowHeight();
|
||||
//
|
||||
// // The new absolute coordinate
|
||||
@ -1262,21 +1125,21 @@ void BufferView::setCursorFromRow(int row)
|
||||
int tmpid = -1;
|
||||
int tmppos = -1;
|
||||
|
||||
buffer_->texrow().getIdFromRow(row, tmpid, tmppos);
|
||||
buffer_.texrow().getIdFromRow(row, tmpid, tmppos);
|
||||
|
||||
cursor_.reset(buffer_->inset());
|
||||
cursor_.reset(buffer_.inset());
|
||||
if (tmpid == -1)
|
||||
buffer_->text().setCursor(cursor_, 0, 0);
|
||||
buffer_.text().setCursor(cursor_, 0, 0);
|
||||
else
|
||||
buffer_->text().setCursor(cursor_, buffer_->getParFromID(tmpid).pit(), tmppos);
|
||||
buffer_.text().setCursor(cursor_, buffer_.getParFromID(tmpid).pit(), tmppos);
|
||||
}
|
||||
|
||||
|
||||
void BufferView::gotoLabel(docstring const & label)
|
||||
{
|
||||
for (InsetIterator it = inset_iterator_begin(buffer_->inset()); it; ++it) {
|
||||
for (InsetIterator it = inset_iterator_begin(buffer_.inset()); it; ++it) {
|
||||
vector<docstring> labels;
|
||||
it->getLabelList(*buffer_, labels);
|
||||
it->getLabelList(buffer_, labels);
|
||||
if (std::find(labels.begin(), labels.end(), label) != labels.end()) {
|
||||
setCursor(it);
|
||||
update();
|
||||
@ -1343,10 +1206,10 @@ bool BufferView::checkDepm(Cursor & cur, Cursor & old)
|
||||
if (!changed)
|
||||
return false;
|
||||
|
||||
updateLabels(*buffer_);
|
||||
updateLabels(buffer_);
|
||||
|
||||
updateMetrics(false);
|
||||
buffer_->changed();
|
||||
buffer_.changed();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1442,7 +1305,7 @@ ViewMetricsInfo const & BufferView::viewMetricsInfo()
|
||||
// FIXME: We should split-up updateMetrics() for the singlepar case.
|
||||
void BufferView::updateMetrics(bool singlepar)
|
||||
{
|
||||
Text & buftext = buffer_->text();
|
||||
Text & buftext = buffer_.text();
|
||||
TextMetrics & tm = textMetrics(&buftext);
|
||||
pit_type size = int(buftext.paragraphs().size());
|
||||
|
||||
@ -1571,13 +1434,10 @@ void BufferView::menuInsertLyXFile(string const & filenm)
|
||||
// Launch a file browser
|
||||
// FIXME UNICODE
|
||||
string initpath = lyxrc.document_path;
|
||||
|
||||
if (buffer_) {
|
||||
string const trypath = buffer_->filePath();
|
||||
// If directory is writeable, use this as default.
|
||||
if (isDirWriteable(FileName(trypath)))
|
||||
initpath = trypath;
|
||||
}
|
||||
string const trypath = buffer_.filePath();
|
||||
// If directory is writeable, use this as default.
|
||||
if (isDirWriteable(FileName(trypath)))
|
||||
initpath = trypath;
|
||||
|
||||
// FIXME UNICODE
|
||||
FileDialog fileDlg(_("Select LyX document to insert"),
|
||||
@ -1617,7 +1477,7 @@ void BufferView::menuInsertLyXFile(string const & filenm)
|
||||
docstring res;
|
||||
Buffer buf("", false);
|
||||
if (lyx::loadLyXFile(&buf, FileName(filename))) {
|
||||
ErrorList & el = buffer_->errorList("Parse");
|
||||
ErrorList & el = buffer_.errorList("Parse");
|
||||
// Copy the inserted document error list into the current buffer one.
|
||||
el = buf.errorList("Parse");
|
||||
recordUndo(cursor_);
|
||||
@ -1629,8 +1489,8 @@ void BufferView::menuInsertLyXFile(string const & filenm)
|
||||
|
||||
// emit message signal.
|
||||
message(bformat(res, disp_fn));
|
||||
buffer_->errors("Parse");
|
||||
resize();
|
||||
buffer_.errors("Parse");
|
||||
updateMetrics(false);
|
||||
}
|
||||
|
||||
} // namespace lyx
|
||||
|
@ -79,20 +79,14 @@ struct ScrollbarParameters
|
||||
*/
|
||||
class BufferView : boost::noncopyable {
|
||||
public:
|
||||
BufferView();
|
||||
///
|
||||
BufferView(Buffer & buffer);
|
||||
|
||||
~BufferView();
|
||||
|
||||
/// set the buffer we are viewing.
|
||||
/// \todo FIXME: eventually, we will create a new BufferView
|
||||
/// when switching Buffers, so this method should go.
|
||||
/// returns the buffer currently set
|
||||
Buffer * setBuffer(Buffer * b);
|
||||
/// return the buffer being viewed.
|
||||
Buffer * buffer() const;
|
||||
|
||||
/// resize the BufferView.
|
||||
void resize();
|
||||
Buffer * buffer();
|
||||
Buffer const * buffer() const;
|
||||
|
||||
/// perform pending metrics updates.
|
||||
/** \c Update::FitCursor means first to do a FitCursor, and to
|
||||
@ -269,7 +263,7 @@ private:
|
||||
///
|
||||
CoordCache coord_cache_;
|
||||
///
|
||||
Buffer * buffer_;
|
||||
Buffer & buffer_;
|
||||
|
||||
/// Estimated average par height for scrollbar.
|
||||
int wh_;
|
||||
|
@ -77,7 +77,15 @@ bool Importer::Import(LyXView * lv, FileName const & filename,
|
||||
|
||||
|
||||
if (loader_format == "lyx") {
|
||||
lv->loadLyXFile(lyxfile);
|
||||
Buffer * buf = lv->loadLyXFile(lyxfile);
|
||||
if (!buf) {
|
||||
// we are done
|
||||
lv->message(_("file not imported!"));
|
||||
return false;
|
||||
}
|
||||
updateLabels(*buf);
|
||||
lv->setBuffer(buf);
|
||||
lv->showErrorList("Parse");
|
||||
} else {
|
||||
Buffer * const b = newFile(lyxfile.absFilename(), string(), true);
|
||||
if (b)
|
||||
|
42
src/LyX.cpp
42
src/LyX.cpp
@ -435,11 +435,12 @@ int LyX::exec(int & argc, char * argv[])
|
||||
}
|
||||
|
||||
BufferList::iterator begin = pimpl_->buffer_list_.begin();
|
||||
BufferList::iterator end = pimpl_->buffer_list_.end();
|
||||
|
||||
bool final_success = false;
|
||||
for (BufferList::iterator I = begin; I != end; ++I) {
|
||||
for (BufferList::iterator I = begin; I != pimpl_->buffer_list_.end(); ++I) {
|
||||
Buffer * buf = *I;
|
||||
if (buf != buf->getMasterBuffer())
|
||||
continue;
|
||||
bool success = false;
|
||||
buf->dispatch(batch_command, &success);
|
||||
final_success |= success;
|
||||
@ -634,25 +635,36 @@ void LyX::restoreGuiSession()
|
||||
if (!pimpl_->files_to_load_.empty()) {
|
||||
for_each(pimpl_->files_to_load_.begin(),
|
||||
pimpl_->files_to_load_.end(),
|
||||
bind(&LyXView::loadLyXFile, view, _1, true, false, false));
|
||||
bind(&LyXView::loadLyXFile, view, _1, true));
|
||||
// clear this list to save a few bytes of RAM
|
||||
pimpl_->files_to_load_.clear();
|
||||
pimpl_->session_->lastOpened().clear();
|
||||
return;
|
||||
|
||||
} else if (lyxrc.load_session) {
|
||||
vector<FileName> const & lastopened = pimpl_->session_->lastOpened().getfiles();
|
||||
// do not add to the lastfile list since these files are restored from
|
||||
// last session, and should be already there (regular files), or should
|
||||
// not be added at all (help files).
|
||||
for_each(lastopened.begin(), lastopened.end(),
|
||||
bind(&LyXView::loadLyXFile, view, _1, false));
|
||||
|
||||
// clear this list to save a few bytes of RAM
|
||||
pimpl_->session_->lastOpened().clear();
|
||||
}
|
||||
|
||||
if (!lyxrc.load_session)
|
||||
return;
|
||||
BufferList::iterator I = pimpl_->buffer_list_.begin();
|
||||
BufferList::iterator end = pimpl_->buffer_list_.end();
|
||||
for (; I != end; ++I) {
|
||||
Buffer * buf = *I;
|
||||
if (buf != buf->getMasterBuffer())
|
||||
continue;
|
||||
updateLabels(*buf);
|
||||
}
|
||||
|
||||
vector<FileName> const & lastopened = pimpl_->session_->lastOpened().getfiles();
|
||||
// do not add to the lastfile list since these files are restored from
|
||||
// last session, and should be already there (regular files), or should
|
||||
// not be added at all (help files).
|
||||
for_each(lastopened.begin(), lastopened.end(),
|
||||
bind(&LyXView::loadLyXFile, view, _1, false, false, false));
|
||||
|
||||
// clear this list to save a few bytes of RAM
|
||||
pimpl_->session_->lastOpened().clear();
|
||||
// FIXME: Switch to the last loaded Buffer. This must not be the first one
|
||||
// because the Buffer won't be connected in this case. The correct solution
|
||||
// would be to avoid the manual connection of the current Buffer in LyXView.
|
||||
view->setBuffer(pimpl_->buffer_list_.last());
|
||||
}
|
||||
|
||||
|
||||
|
@ -124,7 +124,7 @@ void LyXAction::init()
|
||||
{ LFUN_BUFFER_NEW, "buffer-new", NoBuffer },
|
||||
{ LFUN_BUFFER_NEW_TEMPLATE,"buffer-new-template", NoBuffer },
|
||||
{ LFUN_BUFFER_RELOAD, "buffer-reload", ReadOnly },
|
||||
{ LFUN_BUFFER_SWITCH, "buffer-switch", ReadOnly },
|
||||
{ LFUN_BUFFER_SWITCH, "buffer-switch", NoBuffer | ReadOnly },
|
||||
{ LFUN_BUFFER_TOGGLE_READ_ONLY, "buffer-toggle-read-only", ReadOnly },
|
||||
{ LFUN_BUFFER_UPDATE, "buffer-update", ReadOnly },
|
||||
{ LFUN_BUFFER_VIEW, "buffer-view", ReadOnly },
|
||||
|
130
src/LyXFunc.cpp
130
src/LyXFunc.cpp
@ -85,8 +85,9 @@
|
||||
#include "frontends/KeySymbol.h"
|
||||
#include "frontends/LyXView.h"
|
||||
#include "frontends/Menubar.h"
|
||||
#include "frontends/Toolbars.h"
|
||||
#include "frontends/Selection.h"
|
||||
#include "frontends/Toolbars.h"
|
||||
#include "frontends/WorkArea.h"
|
||||
|
||||
#include "support/environment.h"
|
||||
#include "support/FileFilterList.h"
|
||||
@ -221,7 +222,7 @@ void LyXFunc::initKeySequences(KeyMap * kb)
|
||||
|
||||
void LyXFunc::setLyXView(LyXView * lv)
|
||||
{
|
||||
if (!quitting && lyx_view_ && lyx_view_ != lv)
|
||||
if (!quitting && lyx_view_ && lyx_view_->view() && lyx_view_ != lv)
|
||||
// save current selection to the selection buffer to allow
|
||||
// middle-button paste in another window
|
||||
cap::saveSelection(lyx_view_->view()->cursor());
|
||||
@ -385,6 +386,12 @@ void LyXFunc::processKeySym(KeySymbolPtr keysym, key_modifier::state state)
|
||||
} else {
|
||||
dispatch(func);
|
||||
}
|
||||
|
||||
/* When we move around, or type, it's nice to be able to see
|
||||
* the cursor immediately after the keypress.
|
||||
*/
|
||||
if (lyx_view_ && lyx_view_->currentWorkArea())
|
||||
lyx_view_->currentWorkArea()->startBlinkingCursor();
|
||||
}
|
||||
|
||||
|
||||
@ -903,15 +910,17 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
// --- Menus -----------------------------------------------
|
||||
case LFUN_BUFFER_NEW:
|
||||
menuNew(argument, false);
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_NEW_TEMPLATE:
|
||||
menuNew(argument, true);
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_CLOSE:
|
||||
closeBuffer();
|
||||
view()->update();
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_WRITE:
|
||||
@ -1187,7 +1196,13 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
}
|
||||
lyx_view_->message(bformat(_("Opening help file %1$s..."),
|
||||
makeDisplayPath(fname.absFilename())));
|
||||
lyx_view_->loadLyXFile(fname, false);
|
||||
Buffer * buf = lyx_view_->loadLyXFile(fname, false);
|
||||
if (buf) {
|
||||
updateLabels(*buf);
|
||||
lyx_view_->setBuffer(buf);
|
||||
lyx_view_->showErrorList("Parse");
|
||||
}
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1241,29 +1256,31 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
case LFUN_BUFFER_SWITCH:
|
||||
BOOST_ASSERT(lyx_view_);
|
||||
lyx_view_->setBuffer(theBufferList().getBuffer(argument));
|
||||
updateFlags = Update::Force;
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_NEXT:
|
||||
BOOST_ASSERT(lyx_view_);
|
||||
lyx_view_->setBuffer(theBufferList().next(lyx_view_->buffer()));
|
||||
updateFlags = Update::Force;
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_BUFFER_PREVIOUS:
|
||||
BOOST_ASSERT(lyx_view_);
|
||||
lyx_view_->setBuffer(theBufferList().previous(lyx_view_->buffer()));
|
||||
updateFlags = Update::Force;
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_FILE_NEW:
|
||||
BOOST_ASSERT(lyx_view_);
|
||||
newFile(*lyx_view_, argument);
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_FILE_OPEN:
|
||||
BOOST_ASSERT(lyx_view_);
|
||||
open(argument);
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
|
||||
case LFUN_DROP_LAYOUTS_CHOICE:
|
||||
@ -1296,24 +1313,35 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
int row;
|
||||
istringstream is(argument);
|
||||
is >> file_name >> row;
|
||||
if (prefixIs(file_name, package().temp_dir().absFilename())) {
|
||||
Buffer * buf = 0;
|
||||
bool loaded = false;
|
||||
if (prefixIs(file_name, package().temp_dir().absFilename()))
|
||||
// Needed by inverse dvi search. If it is a file
|
||||
// in tmpdir, call the apropriated function
|
||||
lyx_view_->setBuffer(theBufferList().getBufferFromTmp(file_name));
|
||||
} else {
|
||||
buf = theBufferList().getBufferFromTmp(file_name);
|
||||
else {
|
||||
// Must replace extension of the file to be .lyx
|
||||
// and get full path
|
||||
FileName const s = fileSearch(string(), changeExtension(file_name, ".lyx"), "lyx");
|
||||
// Either change buffer or load the file
|
||||
if (theBufferList().exists(s.absFilename())) {
|
||||
lyx_view_->setBuffer(theBufferList().getBuffer(s.absFilename()));
|
||||
} else {
|
||||
lyx_view_->loadLyXFile(s);
|
||||
if (theBufferList().exists(s.absFilename()))
|
||||
buf = theBufferList().getBuffer(s.absFilename());
|
||||
else {
|
||||
buf = lyx_view_->loadLyXFile(s);
|
||||
loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
view()->setCursorFromRow(row);
|
||||
if (!buf) {
|
||||
updateFlags = Update::None;
|
||||
break;
|
||||
}
|
||||
|
||||
updateLabels(*buf);
|
||||
lyx_view_->setBuffer(buf);
|
||||
view()->setCursorFromRow(row);
|
||||
if (loaded)
|
||||
lyx_view_->showErrorList("Parse");
|
||||
updateFlags = Update::FitCursor;
|
||||
break;
|
||||
}
|
||||
@ -1472,36 +1500,33 @@ void LyXFunc::dispatch(FuncRequest const & cmd)
|
||||
}
|
||||
|
||||
case LFUN_BUFFER_CHILD_OPEN: {
|
||||
// takes an optional argument, "|bool", at the end
|
||||
// indicating whether this file is being opened automatically
|
||||
// by LyX itself, in which case we will not want to switch
|
||||
// buffers after opening. The default is false, so in practice
|
||||
// it is used only when true.
|
||||
BOOST_ASSERT(lyx_view_);
|
||||
int const arglength = argument.length();
|
||||
FileName filename;
|
||||
bool autoOpen = false;
|
||||
if (argument.substr(arglength - 5, 5) == "|true") {
|
||||
autoOpen = true;
|
||||
filename = makeAbsPath(argument.substr(0, arglength - 5),
|
||||
lyx_view_->buffer()->filePath());
|
||||
} else if (argument.substr(arglength - 6, 6) == "|false") {
|
||||
filename = makeAbsPath(argument.substr(0, arglength - 6),
|
||||
lyx_view_->buffer()->filePath());
|
||||
} else filename =
|
||||
makeAbsPath(argument, lyx_view_->buffer()->filePath());
|
||||
BOOST_ASSERT(lyx_view_ && lyx_view_->buffer());
|
||||
Buffer * parent = lyx_view_->buffer();
|
||||
FileName filename = makeAbsPath(argument, parent->filePath());
|
||||
view()->saveBookmark(false);
|
||||
Buffer * child = 0;
|
||||
bool parsed = false;
|
||||
if (theBufferList().exists(filename.absFilename())) {
|
||||
Buffer * buf = theBufferList().getBuffer(filename.absFilename());
|
||||
if (!autoOpen)
|
||||
lyx_view_->setBuffer(buf, true);
|
||||
else
|
||||
buf->setParentName(lyx_view_->buffer()->fileName());
|
||||
} else
|
||||
lyx_view_->loadLyXFile(filename, true, true, autoOpen);
|
||||
child = theBufferList().getBuffer(filename.absFilename());
|
||||
} else {
|
||||
setMessage(bformat(_("Opening child document %1$s..."),
|
||||
makeDisplayPath(filename.absFilename())));
|
||||
child = lyx_view_->loadLyXFile(filename, true);
|
||||
parsed = true;
|
||||
}
|
||||
if (child) {
|
||||
// Set the parent name of the child document.
|
||||
// This makes insertion of citations and references in the child work,
|
||||
// when the target is in the parent or another child document.
|
||||
child->setParentName(parent->fileName());
|
||||
updateLabels(*child->getMasterBuffer());
|
||||
lyx_view_->setBuffer(child);
|
||||
if (parsed)
|
||||
lyx_view_->showErrorList("Parse");
|
||||
}
|
||||
|
||||
// If a screen update is required (in case where auto_open is false),
|
||||
// loadLyXFile() would have taken care of it already. Otherwise we shall
|
||||
// setBuffer() would have taken care of it already. Otherwise we shall
|
||||
// reset the update flag because it can cause a circular problem.
|
||||
// See bug 3970.
|
||||
updateFlags = Update::None;
|
||||
@ -1997,10 +2022,8 @@ void LyXFunc::menuNew(string const & name, bool fromTemplate)
|
||||
}
|
||||
|
||||
Buffer * const b = newFile(filename, templname, !name.empty());
|
||||
if (b) {
|
||||
updateLabels(*b);
|
||||
if (b)
|
||||
lyx_view_->setBuffer(b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2060,7 +2083,11 @@ void LyXFunc::open(string const & fname)
|
||||
lyx_view_->message(bformat(_("Opening document %1$s..."), disp_fn));
|
||||
|
||||
docstring str2;
|
||||
if (lyx_view_->loadLyXFile(fullname)) {
|
||||
Buffer * buf = lyx_view_->loadLyXFile(fullname);
|
||||
if (buf) {
|
||||
updateLabels(*buf);
|
||||
lyx_view_->setBuffer(buf);
|
||||
lyx_view_->showErrorList("Parse");
|
||||
str2 = bformat(_("Document %1$s opened."), disp_fn);
|
||||
} else {
|
||||
str2 = bformat(_("Could not open document %1$s"), disp_fn);
|
||||
@ -2169,8 +2196,19 @@ void LyXFunc::closeBuffer()
|
||||
void LyXFunc::reloadBuffer()
|
||||
{
|
||||
FileName filename(lyx_view_->buffer()->fileName());
|
||||
docstring const disp_fn = makeDisplayPath(filename.absFilename());
|
||||
docstring str;
|
||||
closeBuffer();
|
||||
lyx_view_->loadLyXFile(filename);
|
||||
Buffer * buf = lyx_view_->loadLyXFile(filename);
|
||||
if (buf) {
|
||||
updateLabels(*buf);
|
||||
lyx_view_->setBuffer(buf);
|
||||
lyx_view_->showErrorList("Parse");
|
||||
str = bformat(_("Document %1$s reloaded."), disp_fn);
|
||||
} else {
|
||||
str = bformat(_("Could not reload document %1$s"), disp_fn);
|
||||
}
|
||||
lyx_view_->message(str);
|
||||
}
|
||||
|
||||
// Each "lyx_view_" should have it's own message method. lyxview and
|
||||
|
@ -52,14 +52,11 @@ LyXView & Application::createView(unsigned int width,
|
||||
const std::string & geometryArg)
|
||||
{
|
||||
LyXView & view = gui().createRegisteredView();
|
||||
int view_id = view.id();
|
||||
|
||||
theLyXFunc().setLyXView(&view);
|
||||
|
||||
/*int workArea_id_ =*/ gui().newWorkArea(width, height, view_id);
|
||||
|
||||
view.init();
|
||||
view.setGeometry(width, height, posx, posy, maximized, iconSizeXY, geometryArg);
|
||||
|
||||
view.setFocus();
|
||||
|
||||
setCurrentView(view);
|
||||
|
@ -34,29 +34,56 @@ class Selection;
|
||||
There should be only one instance of this class. No Qt object
|
||||
initialisation should be done before the instanciation of this class.
|
||||
|
||||
\todo The work areas handling could be moved to a base virtual class
|
||||
common to all frontends.
|
||||
Model/View/Controller separation at frontend level in LyX-qt4:
|
||||
|
||||
BufferList (N Buffers)
|
||||
|
|
||||
Buffer-a
|
||||
Buffer-b
|
||||
Buffer-c
|
||||
Buffer-d
|
||||
|
||||
Application (this is the frontend really, should probably be renamed).
|
||||
|
|
||||
LyXView-1 (M1 WorkAreas, M1 <= N)
|
||||
| |
|
||||
| <tab-widget>
|
||||
| | (many)
|
||||
| WorkArea-1
|
||||
| |
|
||||
| BufferView <-----------> Buffer-c
|
||||
| |
|
||||
| Cursor
|
||||
|
|
||||
LyXView-2 (M2 WorkAreas, M2 <= N, M2 independent of M1)
|
||||
|
|
||||
...
|
||||
|
||||
Model/View/Controller separation in LyX:
|
||||
|
||||
1) The Model: \c Buffer
|
||||
|
||||
The Buffer is the in-memory representation of a LyX file format. The
|
||||
Buffer does not (should not) have any information on what part of it
|
||||
is represented on screen. There is one unique Buffer per opened LyX
|
||||
file.
|
||||
file. A Buffer may or may not be represented on screen; typically, a
|
||||
child document does not have an associated BufferView unless the user
|
||||
choose to visualize it.
|
||||
|
||||
|
||||
2) The Controller: \c BufferView / \c Painter
|
||||
2) The Controller: \c BufferView / \c Painter \c Cursor
|
||||
|
||||
The BufferView is a tool used by the view that translates a part of
|
||||
the Buffer contents into drawing routines. The BufferView asks each
|
||||
inset of the Buffer to draw itself onto the screen using the Painter.
|
||||
There can be only one Buffer displayed in a BufferView. While there
|
||||
is the possibility to switch Buffer inside the BufferView, the goal
|
||||
is to instantiate a new BufferView on each Buffer switch.
|
||||
The BufferView is a tool used by the view (\sa WorkArea) that
|
||||
translates a part of the Buffer contents into drawing routines. The
|
||||
BufferView asks each inset of the Buffer to draw itself onto the
|
||||
screen using the Painter. There can be only one Buffer displayed in
|
||||
a BufferView and it is set on construction. Ideally, a BufferView
|
||||
should not be able to change the contents of its associated Buffer.
|
||||
A BufferView is instanciated and destroyed by a \c WorkArea; it is
|
||||
automatically destroyed by the parent WorkArea when its Buffer is
|
||||
closed.
|
||||
|
||||
\todo Instantiate a new BufferView on each Buffer switch.
|
||||
\todo Move all Buffer changing LFUN to LyXFunc or Cursor.
|
||||
\todo BufferView::buffer() should only offer const access.
|
||||
|
||||
The \c Painter is just a virtual interface to formalize each kind of
|
||||
drawing routines (text, line, rectangle, etc).
|
||||
@ -69,9 +96,10 @@ common to all frontends.
|
||||
3) The View: \c WorkArea (and it's qt4 specialisation GuiWorkArea)
|
||||
|
||||
This contains the real screen area where the drawing is done by the
|
||||
Painter. One WorkArea holds one unique \c BufferView. While it could be
|
||||
possible that multiple WorkArea share one BufferView, this is not
|
||||
possible right now.
|
||||
Painter. One WorkArea holds one unique \c BufferView. While it could
|
||||
be possible that multiple WorkArea share one BufferView, this is not
|
||||
something desirable because a BufferView is dependent of the WorkArea
|
||||
size.
|
||||
The WorkArea also provide a scrollbar which position is translated
|
||||
into scrolling command to the inner \c BufferView.
|
||||
|
||||
@ -84,18 +112,32 @@ common to all frontends.
|
||||
|
||||
4) The Window: \c LyXView (and its qt4 specialisation \c GuiView)
|
||||
|
||||
This is a full window containing a menubar, toolbars, a tabbar and a
|
||||
WorkArea. One LyXView could in theory contain multiple WorkArea
|
||||
(ex: with split window) but this number is limited to one only for
|
||||
now. In any case, there would be only one WorkArea that gets the focus
|
||||
This is a full window containing a menubar, toolbars and a central
|
||||
widget. A LyXView is in charge of creating and closing a View for a
|
||||
given Buffer.
|
||||
In the qt4 specialisation, \c GuiView, the central widget is a tab
|
||||
widget. Each tab is reverved to the visualisation of one Buffer and
|
||||
contains one WorkArea. In the qt4 frontend, one LyXView thus contains
|
||||
multiple WorkAreas but this number can limited to one for another
|
||||
frontend. The idea is that the kernel should not know how a Buffer
|
||||
is displayed on screen; it's the frontend business.
|
||||
In the future, we may also have multiple Workareas showing
|
||||
simultaneously in the same GuiView (ex: with split window).
|
||||
|
||||
\todo Implement split-window
|
||||
|
||||
In any case, there would be only one WorkArea that gets the focus
|
||||
at a time.
|
||||
|
||||
Now, concerning the TabBar versus TabWidget issue. Right now, there is
|
||||
only one WorkArea and the TabBar just used to tell the BufferView inside
|
||||
the WorkArea to switch to this another Buffer.
|
||||
With our current implementation using a QTabWidget, each Tab own its
|
||||
own \c WorkArea. Clicking on a tab switch a WorkArea and not really
|
||||
a Buffer. LFUN_BUFFER_SWITCH will tell the frontend to search the
|
||||
WorkArea associated to this Buffer. The WorkArea is automatically
|
||||
created if not already present.
|
||||
|
||||
A WorkArea is connected to the Buffer::closing signal and is thus
|
||||
automatically destroyed when its Buffer is closed.
|
||||
|
||||
With a TabWidget, each Tab would own its own \c WorkArea. Clicking on a tab
|
||||
would switch a WorkArea instead of a Buffer.
|
||||
*/
|
||||
class Application
|
||||
{
|
||||
|
@ -52,11 +52,6 @@ public:
|
||||
return view_ids_;
|
||||
}
|
||||
|
||||
|
||||
virtual int newWorkArea(unsigned int width, unsigned int height, int view_id) = 0;
|
||||
///
|
||||
virtual WorkArea & workArea(int id) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<int> view_ids_;
|
||||
|
@ -70,8 +70,7 @@ namespace frontend {
|
||||
docstring current_layout;
|
||||
|
||||
LyXView::LyXView(int id)
|
||||
: work_area_(0),
|
||||
toolbars_(new Toolbars(*this)),
|
||||
: toolbars_(new Toolbars(*this)),
|
||||
autosave_timeout_(new Timeout(5000)),
|
||||
dialogs_(new Dialogs(*this)),
|
||||
controlcommand_(new ControlCommandBuffer(*this)), id_(id)
|
||||
@ -88,177 +87,95 @@ LyXView::LyXView(int id)
|
||||
LyXView::~LyXView()
|
||||
{
|
||||
disconnectBuffer();
|
||||
disconnectBufferView();
|
||||
}
|
||||
|
||||
|
||||
// FIXME, there's only one WorkArea per LyXView possible for now.
|
||||
void LyXView::setWorkArea(WorkArea * work_area)
|
||||
Buffer * LyXView::buffer()
|
||||
{
|
||||
BOOST_ASSERT(work_area);
|
||||
work_area_ = work_area;
|
||||
work_area_ids_.clear();
|
||||
work_area_ids_.push_back(work_area_->id());
|
||||
WorkArea * work_area = currentWorkArea();
|
||||
if (work_area)
|
||||
return work_area->bufferView().buffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// FIXME, there's only one WorkArea per LyXView possible for now.
|
||||
WorkArea const * LyXView::currentWorkArea() const
|
||||
Buffer const * LyXView::buffer() const
|
||||
{
|
||||
return work_area_;
|
||||
WorkArea const * work_area = currentWorkArea();
|
||||
if (work_area)
|
||||
return work_area->bufferView().buffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// FIXME, there's only one WorkArea per LyXView possible for now.
|
||||
WorkArea * LyXView::currentWorkArea()
|
||||
{
|
||||
return work_area_;
|
||||
}
|
||||
|
||||
|
||||
Buffer * LyXView::buffer() const
|
||||
{
|
||||
BOOST_ASSERT(work_area_);
|
||||
return work_area_->bufferView().buffer();
|
||||
}
|
||||
|
||||
|
||||
void LyXView::setBuffer(Buffer * b, bool child_document)
|
||||
void LyXView::setBuffer(Buffer * newBuffer)
|
||||
{
|
||||
busy(true);
|
||||
|
||||
BOOST_ASSERT(work_area_);
|
||||
Buffer * oldBuffer = work_area_->bufferView().buffer();
|
||||
Buffer * oldBuffer = buffer();
|
||||
if (oldBuffer == newBuffer) {
|
||||
busy(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// parentfilename will be used in case when we switch to a child
|
||||
// document (hence when child_document is true)
|
||||
string parentfilename;
|
||||
if (oldBuffer)
|
||||
parentfilename = oldBuffer->fileName();
|
||||
|
||||
if (!b && theBufferList().empty())
|
||||
getDialogs().hideBufferDependent();
|
||||
|
||||
Buffer * newBuffer = work_area_->bufferView().setBuffer(b);
|
||||
|
||||
if (newBuffer) {
|
||||
//Are we closing an oldBuffer which was a child document?
|
||||
if (!b && oldBuffer && oldBuffer->getMasterBuffer() != oldBuffer)
|
||||
// Update the labels and section numbering of its master Buffer.
|
||||
updateLabels(*oldBuffer->getMasterBuffer());
|
||||
//Are we opening a new child document?
|
||||
else if (child_document && newBuffer->getMasterBuffer() != oldBuffer) {
|
||||
// Set the parent name of the child document.
|
||||
// This makes insertion of citations and references in the child work,
|
||||
// when the target is in the parent or another child document.
|
||||
newBuffer->setParentName(parentfilename);
|
||||
// Update the labels and section numbering to the new master Buffer.
|
||||
updateLabels(*newBuffer->getMasterBuffer());
|
||||
}
|
||||
//Now that all the updating of the old buffer has been done, we can
|
||||
//connect the new buffer. Note that this will also disconnect the old
|
||||
//buffer, if such there is.
|
||||
//FIXME Is it clear that this should go right here? Or should it go
|
||||
//earlier before the previous if (in which case we'd remove the "else")?
|
||||
connectBuffer(*newBuffer);
|
||||
|
||||
/* FIXME: We need to rebuild the Toc dialog before the others even
|
||||
if it will be rebuilt again in the next line. This avoid a crash when
|
||||
other dialogs are rebuilt before the Toc dialog. The reason is
|
||||
that closing a Buffer triggers an update of all opened dialogs
|
||||
when dispatching LFUN_DIALOG_UPDATE (hence the patch).
|
||||
The path is as following:
|
||||
setBuffer() -> updateBufferDependent() -> RestoreButton() -> LFUN
|
||||
The problem here is that the Toc dialog has not been
|
||||
reconstructed (because it comes after in the list of dialogs). */
|
||||
updateToc();
|
||||
|
||||
// Buffer-dependent dialogs should be updated or
|
||||
// hidden. This should go here because some dialogs (eg ToC)
|
||||
// require bv_->text.
|
||||
getDialogs().updateBufferDependent(true);
|
||||
WorkArea * wa = workArea(*newBuffer);
|
||||
if (wa == 0) {
|
||||
updateLabels(*newBuffer->getMasterBuffer());
|
||||
wa = addWorkArea(*newBuffer);
|
||||
} else
|
||||
//Disconnect the old buffer...there's no new one.
|
||||
disconnectBuffer();
|
||||
connectBuffer(*newBuffer);
|
||||
connectBufferView(wa->bufferView());
|
||||
setCurrentWorkArea(wa);
|
||||
|
||||
if (quitting)
|
||||
return;
|
||||
|
||||
updateMenubar();
|
||||
updateToolbars();
|
||||
updateLayoutChoice();
|
||||
updateWindowTitle();
|
||||
updateStatusBar();
|
||||
updateTab();
|
||||
busy(false);
|
||||
work_area_->redraw();
|
||||
}
|
||||
|
||||
|
||||
bool LyXView::loadLyXFile(FileName const & filename, bool tolastfiles,
|
||||
bool child_document, bool auto_open)
|
||||
Buffer * LyXView::loadLyXFile(FileName const & filename, bool tolastfiles)
|
||||
{
|
||||
busy(true);
|
||||
|
||||
BOOST_ASSERT(work_area_);
|
||||
string parentfilename;
|
||||
Buffer * oldBuffer = work_area_->bufferView().buffer();
|
||||
Buffer * oldBuffer = buffer();
|
||||
if (oldBuffer)
|
||||
parentfilename = oldBuffer->fileName();
|
||||
|
||||
bool alreadyLoaded = checkIfLoaded(filename);
|
||||
Buffer * newBuffer = checkAndLoadLyXFile(filename);
|
||||
|
||||
if (!newBuffer) {
|
||||
message(_("Document not loaded."));
|
||||
updateStatusBar();
|
||||
busy(false);
|
||||
work_area_->redraw();
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (child_document && newBuffer != oldBuffer) {
|
||||
// Set the parent name of the child document.
|
||||
// This makes insertion of citations and references in the child work,
|
||||
// when the target is in the parent or another child document.
|
||||
newBuffer->setParentName(parentfilename);
|
||||
message(bformat(_("Opening child document %1$s..."),
|
||||
makeDisplayPath(filename.absFilename())));
|
||||
}
|
||||
WorkArea * wa = addWorkArea(*newBuffer);
|
||||
|
||||
// Update the labels and section numbering.
|
||||
updateLabels(*newBuffer->getMasterBuffer());
|
||||
|
||||
bool const parse_error = !newBuffer->errorList("Parse").empty();
|
||||
bool const need_switch = parse_error || !auto_open;
|
||||
if (need_switch) {
|
||||
setBuffer(newBuffer, child_document);
|
||||
if (!alreadyLoaded) {
|
||||
if (parse_error)
|
||||
showErrorList("Parse");
|
||||
// scroll to the position when the file was last closed
|
||||
if (lyxrc.use_lastfilepos) {
|
||||
pit_type pit;
|
||||
pos_type pos;
|
||||
boost::tie(pit, pos) = LyX::ref().session().lastFilePos().load(filename);
|
||||
// if successfully move to pit (returned par_id is not zero),
|
||||
// update metrics and reset font
|
||||
if (work_area_->bufferView().moveToPosition(pit, pos, 0, 0).get<1>()) {
|
||||
if (work_area_->bufferView().fitCursor())
|
||||
work_area_->bufferView().updateMetrics(false);
|
||||
newBuffer->text().setCurrentFont(work_area_->bufferView().cursor());
|
||||
updateMenubar();
|
||||
updateToolbars();
|
||||
updateLayoutChoice();
|
||||
updateStatusBar();
|
||||
work_area_->redraw();
|
||||
}
|
||||
}
|
||||
if (tolastfiles)
|
||||
LyX::ref().session().lastFiles().add(filename);
|
||||
// scroll to the position when the file was last closed
|
||||
if (lyxrc.use_lastfilepos) {
|
||||
pit_type pit;
|
||||
pos_type pos;
|
||||
boost::tie(pit, pos) = LyX::ref().session().lastFilePos().load(filename);
|
||||
// if successfully move to pit (returned par_id is not zero),
|
||||
// update metrics and reset font
|
||||
BufferView & bv = wa->bufferView();
|
||||
if (bv.moveToPosition(pit, pos, 0, 0).get<1>()) {
|
||||
if (bv.fitCursor())
|
||||
bv.updateMetrics(false);
|
||||
newBuffer->text().setCurrentFont(bv.cursor());
|
||||
}
|
||||
}
|
||||
|
||||
busy(false);
|
||||
return true;
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
|
||||
@ -267,11 +184,6 @@ void LyXView::connectBuffer(Buffer & buf)
|
||||
if (errorsConnection_.connected())
|
||||
disconnectBuffer();
|
||||
|
||||
BOOST_ASSERT(work_area_);
|
||||
bufferChangedConnection_ =
|
||||
buf.changed.connect(
|
||||
boost::bind(&WorkArea::redraw, work_area_));
|
||||
|
||||
bufferStructureChangedConnection_ =
|
||||
buf.getMasterBuffer()->structureChanged.connect(
|
||||
boost::bind(&LyXView::updateToc, this));
|
||||
@ -299,30 +211,26 @@ void LyXView::connectBuffer(Buffer & buf)
|
||||
readonlyConnection_ =
|
||||
buf.readonly.connect(
|
||||
boost::bind(&LyXView::showReadonly, this, _1));
|
||||
|
||||
closingConnection_ =
|
||||
buf.closing.connect(
|
||||
boost::bind(&LyXView::setBuffer, this, (Buffer *)0, false));
|
||||
}
|
||||
|
||||
|
||||
void LyXView::disconnectBuffer()
|
||||
{
|
||||
errorsConnection_.disconnect();
|
||||
bufferChangedConnection_.disconnect();
|
||||
bufferStructureChangedConnection_.disconnect();
|
||||
messageConnection_.disconnect();
|
||||
busyConnection_.disconnect();
|
||||
titleConnection_.disconnect();
|
||||
timerConnection_.disconnect();
|
||||
readonlyConnection_.disconnect();
|
||||
closingConnection_.disconnect();
|
||||
layout_changed_connection_.disconnect();
|
||||
}
|
||||
|
||||
|
||||
void LyXView::connectBufferView(BufferView & bv)
|
||||
{
|
||||
message_connection_ = bv.message.connect(
|
||||
boost::bind(&LyXView::message, this, _1));
|
||||
show_dialog_connection_ = bv.showDialog.connect(
|
||||
boost::bind(&LyXView::showDialog, this, _1));
|
||||
show_dialog_with_data_connection_ = bv.showDialogWithData.connect(
|
||||
@ -338,6 +246,7 @@ void LyXView::connectBufferView(BufferView & bv)
|
||||
|
||||
void LyXView::disconnectBufferView()
|
||||
{
|
||||
message_connection_.disconnect();
|
||||
show_dialog_connection_.disconnect();
|
||||
show_dialog_with_data_connection_.disconnect();
|
||||
show_inset_dialog_connection_.disconnect();
|
||||
@ -387,10 +296,10 @@ void LyXView::showReadonly(bool)
|
||||
}
|
||||
|
||||
|
||||
BufferView * LyXView::view() const
|
||||
BufferView * LyXView::view()
|
||||
{
|
||||
BOOST_ASSERT(work_area_);
|
||||
return &work_area_->bufferView();
|
||||
WorkArea * wa = currentWorkArea();
|
||||
return wa? &wa->bufferView() : 0;
|
||||
}
|
||||
|
||||
|
||||
@ -402,16 +311,20 @@ void LyXView::updateToc()
|
||||
|
||||
void LyXView::updateToolbars()
|
||||
{
|
||||
BOOST_ASSERT(work_area_);
|
||||
bool const math =
|
||||
work_area_->bufferView().cursor().inMathed();
|
||||
bool const table =
|
||||
lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
|
||||
bool const review =
|
||||
lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
|
||||
lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
|
||||
WorkArea * wa = currentWorkArea();
|
||||
if (wa) {
|
||||
bool const math =
|
||||
wa->bufferView().cursor().inMathed();
|
||||
bool const table =
|
||||
lyx::getStatus(FuncRequest(LFUN_LAYOUT_TABULAR)).enabled();
|
||||
bool const review =
|
||||
lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).enabled() &&
|
||||
lyx::getStatus(FuncRequest(LFUN_CHANGES_TRACK)).onoff(true);
|
||||
|
||||
toolbars_->update(math, table, review);
|
||||
} else
|
||||
toolbars_->update(false, false, false);
|
||||
|
||||
toolbars_->update(math, table, review);
|
||||
// update redaonly status of open dialogs. This could also be in
|
||||
// updateMenubar(), but since updateToolbars() and updateMenubar()
|
||||
// are always called together it is only here.
|
||||
@ -449,7 +362,7 @@ void LyXView::autoSave()
|
||||
{
|
||||
LYXERR(Debug::INFO) << "Running autoSave()" << endl;
|
||||
|
||||
if (view()->buffer())
|
||||
if (buffer())
|
||||
lyx::autoSave(view());
|
||||
}
|
||||
|
||||
@ -464,7 +377,7 @@ void LyXView::resetAutosaveTimer()
|
||||
void LyXView::updateLayoutChoice()
|
||||
{
|
||||
// Don't show any layouts without a buffer
|
||||
if (!view()->buffer()) {
|
||||
if (!buffer()) {
|
||||
toolbars_->clearLayoutList();
|
||||
return;
|
||||
}
|
||||
@ -474,8 +387,7 @@ void LyXView::updateLayoutChoice()
|
||||
current_layout = buffer()->params().getTextClass().defaultLayoutName();
|
||||
}
|
||||
|
||||
BOOST_ASSERT(work_area_);
|
||||
docstring const & layout = work_area_->bufferView().cursor().
|
||||
docstring const & layout = currentWorkArea()->bufferView().cursor().
|
||||
innerParagraph().layout()->name();
|
||||
|
||||
if (layout != current_layout) {
|
||||
@ -490,42 +402,50 @@ void LyXView::updateWindowTitle()
|
||||
docstring maximize_title = lyx::from_ascii("LyX");
|
||||
docstring minimize_title = lyx::from_ascii("LyX");
|
||||
|
||||
if (view()->buffer()) {
|
||||
string const cur_title = buffer()->fileName();
|
||||
Buffer * buf = buffer();
|
||||
if (buf) {
|
||||
string const cur_title = buf->fileName();
|
||||
if (!cur_title.empty()) {
|
||||
maximize_title += ": " + makeDisplayPath(cur_title, 30);
|
||||
minimize_title = lyx::from_utf8(onlyFilename(cur_title));
|
||||
if (!buffer()->isClean()) {
|
||||
if (!buf->isClean()) {
|
||||
maximize_title += _(" (changed)");
|
||||
minimize_title += lyx::char_type('*');
|
||||
}
|
||||
if (buffer()->isReadonly())
|
||||
if (buf->isReadonly())
|
||||
maximize_title += _(" (read only)");
|
||||
}
|
||||
}
|
||||
|
||||
setWindowTitle(maximize_title, minimize_title);
|
||||
updateTab();
|
||||
}
|
||||
|
||||
|
||||
void LyXView::dispatch(FuncRequest const & cmd)
|
||||
{
|
||||
theLyXFunc().setLyXView(this);
|
||||
lyx::dispatch(cmd);
|
||||
string const argument = to_utf8(cmd.argument());
|
||||
switch(cmd.action) {
|
||||
case LFUN_BUFFER_SWITCH:
|
||||
setBuffer(theBufferList().getBuffer(to_utf8(cmd.argument())));
|
||||
break;
|
||||
default:
|
||||
theLyXFunc().setLyXView(this);
|
||||
lyx::dispatch(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Buffer const * const LyXView::updateInset(Inset const * inset) const
|
||||
Buffer const * const LyXView::updateInset(Inset const * inset)
|
||||
{
|
||||
Buffer const * buffer_ptr = 0;
|
||||
if (inset) {
|
||||
BOOST_ASSERT(work_area_);
|
||||
work_area_->scheduleRedraw();
|
||||
WorkArea * work_area = currentWorkArea();
|
||||
if (!work_area)
|
||||
return 0;
|
||||
|
||||
buffer_ptr = work_area_->bufferView().buffer();
|
||||
if (inset) {
|
||||
BOOST_ASSERT(work_area);
|
||||
work_area->scheduleRedraw();
|
||||
}
|
||||
return buffer_ptr;
|
||||
return work_area->bufferView().buffer();
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
|
@ -70,16 +70,19 @@ public:
|
||||
|
||||
virtual void setFocus() = 0;
|
||||
|
||||
std::vector<int> const & workAreaIds() const { return work_area_ids_; }
|
||||
|
||||
/// FIXME: rename to setCurrentWorkArea()
|
||||
void setWorkArea(WorkArea * work_area);
|
||||
|
||||
///
|
||||
virtual WorkArea * workArea(Buffer & buffer) = 0;
|
||||
///
|
||||
virtual WorkArea * addWorkArea(Buffer & buffer) = 0;
|
||||
///
|
||||
virtual void setCurrentWorkArea(WorkArea * work_area) = 0;
|
||||
///
|
||||
virtual void removeWorkArea(WorkArea * work_area) = 0;
|
||||
/// return the current WorkArea (the one that has the focus).
|
||||
WorkArea const * currentWorkArea() const;
|
||||
virtual WorkArea const * currentWorkArea() const = 0;
|
||||
/// FIXME: This non-const access is needed because of
|
||||
/// a mis-designed \c ControlSpellchecker.
|
||||
WorkArea * currentWorkArea();
|
||||
virtual WorkArea * currentWorkArea() = 0;
|
||||
|
||||
/**
|
||||
* This is called after the concrete view has been created.
|
||||
@ -114,14 +117,12 @@ public:
|
||||
|
||||
//@{ generic accessor functions
|
||||
|
||||
/** return the current buffer view
|
||||
Returned as a shared_ptr so that anything wanting to cache the
|
||||
buffer view can do so safely using a boost::weak_ptr.
|
||||
*/
|
||||
BufferView * view() const;
|
||||
/// \return the current buffer view.
|
||||
BufferView * view();
|
||||
|
||||
/// return the buffer currently shown in this window
|
||||
Buffer * buffer() const;
|
||||
/// \return the buffer currently shown in this window
|
||||
Buffer * buffer();
|
||||
Buffer const * buffer() const;
|
||||
|
||||
/// return the toolbar for this view
|
||||
Toolbars & getToolbars() { return *toolbars_.get(); }
|
||||
@ -141,14 +142,11 @@ public:
|
||||
//@}
|
||||
|
||||
/// load a buffer into the current workarea.
|
||||
bool loadLyXFile(support::FileName const & name, ///< File to load.
|
||||
bool tolastfiles = true, ///< append to the "Open recent" menu?
|
||||
bool child_document = false, ///< Is this a child document?
|
||||
bool auto_open = false); ///< Is this being opened by LyX itself?
|
||||
Buffer * loadLyXFile(support::FileName const & name, ///< File to load.
|
||||
bool tolastfiles = true); ///< append to the "Open recent" menu?
|
||||
|
||||
/// set a buffer to the current workarea.
|
||||
void setBuffer(Buffer * b, ///< \c Buffer to set.
|
||||
bool child_document = false); ///< Is this a child document?
|
||||
void setBuffer(Buffer * b); ///< \c Buffer to set.
|
||||
|
||||
/// updates the possible layouts selectable
|
||||
void updateLayoutChoice();
|
||||
@ -176,9 +174,6 @@ public:
|
||||
/// updates the title of the window
|
||||
void updateWindowTitle();
|
||||
|
||||
/// updates the tab view
|
||||
virtual void updateTab() = 0;
|
||||
|
||||
/// reset autosave timer
|
||||
void resetAutosaveTimer();
|
||||
|
||||
@ -188,7 +183,7 @@ public:
|
||||
/** redraw \c inset in all the BufferViews in which it is currently
|
||||
* visible. If successful return a pointer to the owning Buffer.
|
||||
*/
|
||||
Buffer const * const updateInset(Inset const *) const;
|
||||
Buffer const * const updateInset(Inset const *);
|
||||
|
||||
/// returns true if this view has the focus.
|
||||
virtual bool hasFocus() const = 0;
|
||||
@ -196,17 +191,15 @@ public:
|
||||
/// show the error list to the user
|
||||
void showErrorList(std::string const &);
|
||||
|
||||
protected:
|
||||
/// connect to signals in the given BufferView
|
||||
void connectBufferView(BufferView & bv);
|
||||
/// disconnect from signals in the given BufferView
|
||||
void disconnectBufferView();
|
||||
|
||||
protected:
|
||||
/// current work area (screen view of a BufferView).
|
||||
/**
|
||||
\todo FIXME: there is only one workArea per LyXView for now.
|
||||
*/
|
||||
frontend::WorkArea * work_area_;
|
||||
/// connect to signals in the given buffer
|
||||
void connectBuffer(Buffer & buf);
|
||||
/// disconnect from signals in the given buffer
|
||||
void disconnectBuffer();
|
||||
|
||||
/// view's menubar
|
||||
boost::scoped_ptr<Menubar> menubar_;
|
||||
@ -231,8 +224,6 @@ private:
|
||||
/// dialogs for this view
|
||||
boost::scoped_ptr<Dialogs> dialogs_;
|
||||
|
||||
/// buffer changed signal connection
|
||||
boost::signals::connection bufferChangedConnection_;
|
||||
/// buffer structure changed signal connection
|
||||
boost::signals::connection bufferStructureChangedConnection_;
|
||||
/// buffer errors signal connection
|
||||
@ -247,18 +238,6 @@ private:
|
||||
boost::signals::connection timerConnection_;
|
||||
/// buffer readonly status changed signal connection
|
||||
boost::signals::connection readonlyConnection_;
|
||||
/// buffer closing signal connection
|
||||
boost::signals::connection closingConnection_;
|
||||
/// connect to signals in the given buffer
|
||||
void connectBuffer(Buffer & buf);
|
||||
/// disconnect from signals in the given buffer
|
||||
/// NOTE: Do not call this unless you really want no buffer
|
||||
/// to be connected---for example, when closing the last open
|
||||
/// buffer. If you are switching buffers, just call
|
||||
/// connectBuffer(), and the old buffer will be disconnected
|
||||
/// automatically. This ensures that we do not leave LyX in a
|
||||
/// state in which no buffer is connected.
|
||||
void disconnectBuffer();
|
||||
|
||||
/// BufferView messages signal connection
|
||||
//@{
|
||||
@ -298,7 +277,6 @@ protected:
|
||||
|
||||
private:
|
||||
int id_;
|
||||
std::vector<int> work_area_ids_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
@ -17,26 +17,27 @@
|
||||
|
||||
#include "frontends/Application.h"
|
||||
#include "frontends/FontMetrics.h"
|
||||
|
||||
#include "FuncRequest.h"
|
||||
#include "LyXFunc.h"
|
||||
#include "frontends/LyXView.h"
|
||||
|
||||
#include "BufferView.h"
|
||||
#include "Buffer.h"
|
||||
#include "BufferParams.h"
|
||||
#include "Color.h"
|
||||
#include "CoordCache.h"
|
||||
#include "Cursor.h"
|
||||
#include "debug.h"
|
||||
#include "Language.h"
|
||||
#include "Color.h"
|
||||
#include "Font.h"
|
||||
#include "FuncRequest.h"
|
||||
#include "Language.h"
|
||||
#include "LyX.h"
|
||||
#include "LyXFunc.h"
|
||||
#include "LyXRC.h"
|
||||
#include "Text.h"
|
||||
#include "LyXView.h"
|
||||
#include "MetricsInfo.h"
|
||||
#include "Text.h"
|
||||
|
||||
#include "gettext.h"
|
||||
#include "support/ForkedcallsController.h"
|
||||
#include "support/FileName.h"
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
@ -64,41 +65,56 @@ boost::signals::connection timecon;
|
||||
namespace lyx {
|
||||
namespace frontend {
|
||||
|
||||
WorkArea::WorkArea(int id, LyXView & lyx_view)
|
||||
: buffer_view_(0), lyx_view_(lyx_view), greyed_out_(true),
|
||||
id_(id), cursor_visible_(false), cursor_timeout_(400)
|
||||
WorkArea::WorkArea(Buffer & buffer, LyXView & lv)
|
||||
: buffer_view_(new BufferView(buffer)), lyx_view_(&lv),
|
||||
cursor_visible_(false), cursor_timeout_(400)
|
||||
{
|
||||
// Start loading the pixmap as soon as possible
|
||||
//if (lyxrc.show_banner) {
|
||||
// showBanner();
|
||||
//}
|
||||
|
||||
// Setup the signals
|
||||
timecon = cursor_timeout_.timeout
|
||||
.connect(boost::bind(&WorkArea::toggleCursor, this));
|
||||
|
||||
bufferChangedConnection_ =
|
||||
buffer.changed.connect(
|
||||
boost::bind(&WorkArea::redraw, this));
|
||||
|
||||
bufferClosingConnection_ =
|
||||
buffer.closing.connect(
|
||||
boost::bind(&WorkArea::close, this));
|
||||
|
||||
cursor_timeout_.start();
|
||||
}
|
||||
|
||||
|
||||
void WorkArea::setBufferView(BufferView * buffer_view)
|
||||
WorkArea::~WorkArea()
|
||||
{
|
||||
if (buffer_view_) {
|
||||
message_connection_.disconnect();
|
||||
lyx_view_.disconnectBufferView();
|
||||
}
|
||||
bufferChangedConnection_.disconnect();
|
||||
bufferClosingConnection_.disconnect();
|
||||
|
||||
hideCursor();
|
||||
buffer_view_ = buffer_view;
|
||||
toggleCursor();
|
||||
// current buffer is going to be switched-off, save cursor pos
|
||||
// Ideally, the whole cursor stack should be saved, but session
|
||||
// currently can only handle bottom (whole document) level pit and pos.
|
||||
// That is to say, if a cursor is in a nested inset, it will be
|
||||
// restore to the left of the top level inset.
|
||||
Cursor & cur = buffer_view_->cursor();
|
||||
LyX::ref().session().lastFilePos().save(
|
||||
support::FileName(buffer_view_->buffer()->fileName()),
|
||||
boost::tie(cur.bottom().pit(), cur.bottom().pos()) );
|
||||
|
||||
message_connection_ = buffer_view_->message.connect(
|
||||
boost::bind(&WorkArea::displayMessage, this, _1));
|
||||
|
||||
lyx_view_.connectBufferView(*buffer_view);
|
||||
delete buffer_view_;
|
||||
}
|
||||
|
||||
|
||||
void WorkArea::close()
|
||||
{
|
||||
lyx_view_->removeWorkArea(this);
|
||||
}
|
||||
|
||||
//void WorkArea::setLyXView(LyXView * lyx_view)
|
||||
//{
|
||||
// lyx_view_ = lyx_view;
|
||||
//}
|
||||
|
||||
|
||||
BufferView & WorkArea::bufferView()
|
||||
{
|
||||
return *buffer_view_;
|
||||
@ -127,16 +143,13 @@ void WorkArea::startBlinkingCursor()
|
||||
|
||||
void WorkArea::redraw()
|
||||
{
|
||||
if (!buffer_view_ || !buffer_view_->buffer()) {
|
||||
greyed_out_ = true;
|
||||
// The argument here are meaningless.
|
||||
expose(1,1,1,1);
|
||||
if (!isVisible())
|
||||
// No need to redraw in this case.
|
||||
return;
|
||||
}
|
||||
|
||||
// No need to do anything if this is the current view. The BufferView
|
||||
// metrics are already up to date.
|
||||
if (&lyx_view_ != theApp()->currentView()) {
|
||||
if (lyx_view_ != theApp()->currentView()) {
|
||||
// FIXME: it would be nice to optimize for the off-screen case.
|
||||
buffer_view_->updateMetrics(false);
|
||||
buffer_view_->cursor().fixIfBroken();
|
||||
@ -152,7 +165,6 @@ void WorkArea::redraw()
|
||||
}
|
||||
|
||||
ViewMetricsInfo const & vi = buffer_view_->viewMetricsInfo();
|
||||
greyed_out_ = false;
|
||||
|
||||
LYXERR(Debug::WORKAREA) << "WorkArea::redraw screen" << endl;
|
||||
|
||||
@ -176,13 +188,8 @@ void WorkArea::processKeySym(KeySymbolPtr key, key_modifier::state state)
|
||||
// the blinking cursor.
|
||||
stopBlinkingCursor();
|
||||
|
||||
theLyXFunc().setLyXView(&lyx_view_);
|
||||
theLyXFunc().setLyXView(lyx_view_);
|
||||
theLyXFunc().processKeySym(key, state);
|
||||
|
||||
/* When we move around, or type, it's nice to be able to see
|
||||
* the cursor immediately after the keypress.
|
||||
*/
|
||||
startBlinkingCursor();
|
||||
}
|
||||
|
||||
|
||||
@ -190,11 +197,11 @@ void WorkArea::dispatch(FuncRequest const & cmd0, key_modifier::state k)
|
||||
{
|
||||
// Handle drag&drop
|
||||
if (cmd0.action == LFUN_FILE_OPEN) {
|
||||
lyx_view_.dispatch(cmd0);
|
||||
lyx_view_->dispatch(cmd0);
|
||||
return;
|
||||
}
|
||||
|
||||
theLyXFunc().setLyXView(&lyx_view_);
|
||||
theLyXFunc().setLyXView(lyx_view_);
|
||||
|
||||
FuncRequest cmd;
|
||||
|
||||
@ -222,9 +229,9 @@ void WorkArea::dispatch(FuncRequest const & cmd0, key_modifier::state k)
|
||||
|
||||
// Skip these when selecting
|
||||
if (cmd.action != LFUN_MOUSE_MOTION) {
|
||||
lyx_view_.updateLayoutChoice();
|
||||
lyx_view_.updateMenubar();
|
||||
lyx_view_.updateToolbars();
|
||||
lyx_view_->updateLayoutChoice();
|
||||
lyx_view_->updateMenubar();
|
||||
lyx_view_->updateToolbars();
|
||||
}
|
||||
|
||||
// GUI tweaks except with mouse motion with no button pressed.
|
||||
@ -233,7 +240,7 @@ void WorkArea::dispatch(FuncRequest const & cmd0, key_modifier::state k)
|
||||
// Slight hack: this is only called currently when we
|
||||
// clicked somewhere, so we force through the display
|
||||
// of the new status here.
|
||||
lyx_view_.clearMessage();
|
||||
lyx_view_->clearMessage();
|
||||
|
||||
// Show the cursor immediately after any operation.
|
||||
startBlinkingCursor();
|
||||
@ -243,12 +250,12 @@ void WorkArea::dispatch(FuncRequest const & cmd0, key_modifier::state k)
|
||||
|
||||
void WorkArea::resizeBufferView()
|
||||
{
|
||||
lyx_view_.busy(true);
|
||||
lyx_view_.message(_("Formatting document..."));
|
||||
lyx_view_->busy(true);
|
||||
lyx_view_->message(_("Formatting document..."));
|
||||
buffer_view_->workAreaResize(width(), height());
|
||||
lyx_view_.updateLayoutChoice();
|
||||
lyx_view_.clearMessage();
|
||||
lyx_view_.busy(false);
|
||||
lyx_view_->updateLayoutChoice();
|
||||
lyx_view_->clearMessage();
|
||||
lyx_view_->busy(false);
|
||||
}
|
||||
|
||||
|
||||
@ -268,7 +275,7 @@ void WorkArea::scrollBufferView(int position)
|
||||
redraw();
|
||||
if (lyxrc.cursor_follows_scrollbar) {
|
||||
buffer_view_->setCursorFromScrollbar();
|
||||
lyx_view_.updateLayoutChoice();
|
||||
lyx_view_->updateLayoutChoice();
|
||||
}
|
||||
// Show the cursor immediately after any operation.
|
||||
startBlinkingCursor();
|
||||
@ -280,9 +287,6 @@ void WorkArea::showCursor()
|
||||
if (cursor_visible_)
|
||||
return;
|
||||
|
||||
if (!buffer_view_->buffer())
|
||||
return;
|
||||
|
||||
CursorShape shape = BAR_SHAPE;
|
||||
|
||||
Text const & text = *buffer_view_->cursor().innerText();
|
||||
@ -332,28 +336,19 @@ void WorkArea::hideCursor()
|
||||
|
||||
void WorkArea::toggleCursor()
|
||||
{
|
||||
if (buffer_view_->buffer()) {
|
||||
if (cursor_visible_)
|
||||
hideCursor();
|
||||
else
|
||||
showCursor();
|
||||
|
||||
if (cursor_visible_)
|
||||
hideCursor();
|
||||
else
|
||||
showCursor();
|
||||
|
||||
// Use this opportunity to deal with any child processes that
|
||||
// have finished but are waiting to communicate this fact
|
||||
// to the rest of LyX.
|
||||
ForkedcallsController & fcc = ForkedcallsController::get();
|
||||
fcc.handleCompletedProcesses();
|
||||
}
|
||||
// Use this opportunity to deal with any child processes that
|
||||
// have finished but are waiting to communicate this fact
|
||||
// to the rest of LyX.
|
||||
ForkedcallsController & fcc = ForkedcallsController::get();
|
||||
fcc.handleCompletedProcesses();
|
||||
|
||||
cursor_timeout_.restart();
|
||||
}
|
||||
|
||||
|
||||
void WorkArea::displayMessage(lyx::docstring const & message)
|
||||
{
|
||||
lyx_view_.message(message);
|
||||
}
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace lyx
|
||||
|
@ -25,7 +25,7 @@
|
||||
#undef CursorShape
|
||||
|
||||
namespace lyx {
|
||||
|
||||
class Buffer;
|
||||
class BufferView;
|
||||
class FuncRequest;
|
||||
|
||||
@ -53,13 +53,13 @@ enum CursorShape {
|
||||
*/
|
||||
class WorkArea : public boost::signals::trackable {
|
||||
public:
|
||||
WorkArea(int id, LyXView & lyx_view);
|
||||
///
|
||||
WorkArea(Buffer & buffer, LyXView & lv);
|
||||
|
||||
virtual ~WorkArea() {}
|
||||
virtual ~WorkArea();
|
||||
|
||||
int const id() const { return id_; }
|
||||
|
||||
void setBufferView(BufferView * buffer_view);
|
||||
///
|
||||
void setLyXView(LyXView & lv) { lyx_view_ = &lv; }
|
||||
|
||||
///
|
||||
BufferView & bufferView();
|
||||
@ -69,6 +69,9 @@ public:
|
||||
/// \return true if has the keyboard input focus.
|
||||
virtual bool hasFocus() const = 0;
|
||||
|
||||
/// \return true if has this WorkArea is visible.
|
||||
virtual bool isVisible() const = 0;
|
||||
|
||||
/// return the width of the work area in pixels
|
||||
virtual int width() const = 0;
|
||||
|
||||
@ -95,12 +98,17 @@ public:
|
||||
/// Process Key pressed event.
|
||||
/// This needs to be public because it is accessed externally by GuiView.
|
||||
void processKeySym(KeySymbolPtr key, key_modifier::state state);
|
||||
|
||||
protected:
|
||||
/// cause the display of the given area of the work area
|
||||
virtual void expose(int x, int y, int w, int h) = 0;
|
||||
///
|
||||
void dispatch(FuncRequest const & cmd0,
|
||||
key_modifier::state = key_modifier::none);
|
||||
|
||||
/// close this work area.
|
||||
/// Slot for Buffer::closing boost signal.
|
||||
void close();
|
||||
///
|
||||
void resizeBufferView();
|
||||
///
|
||||
@ -120,25 +128,20 @@ protected:
|
||||
|
||||
///
|
||||
BufferView * buffer_view_;
|
||||
|
||||
///
|
||||
LyXView & lyx_view_;
|
||||
///
|
||||
bool greyed_out_;
|
||||
LyXView * lyx_view_;
|
||||
|
||||
private:
|
||||
///
|
||||
int id_;
|
||||
///
|
||||
void displayMessage(docstring const &);
|
||||
/// buffer messages signal connection
|
||||
boost::signals::connection message_connection_;
|
||||
|
||||
/// is the cursor currently displayed
|
||||
bool cursor_visible_;
|
||||
|
||||
///
|
||||
Timeout cursor_timeout_;
|
||||
|
||||
/// buffer changed signal connection
|
||||
boost::signals::connection bufferChangedConnection_;
|
||||
/// buffer closing signal connection
|
||||
boost::signals::connection bufferClosingConnection_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <QFileOpenEvent>
|
||||
#include <QLocale>
|
||||
#include <QLibraryInfo>
|
||||
#include <QPixmapCache>
|
||||
#include <QTextCodec>
|
||||
#include <QTimer>
|
||||
#include <QTranslator>
|
||||
@ -147,6 +148,10 @@ GuiApplication::GuiApplication(int & argc, char ** argv)
|
||||
LoaderQueue::setPriority(10,100);
|
||||
|
||||
guiApp = this;
|
||||
|
||||
// Set the cache to 5120 kilobytes which corresponds to screen size of
|
||||
// 1280 by 1024 pixels with a color depth of 32 bits.
|
||||
QPixmapCache::setCacheLimit(5120);
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,22 +12,12 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
// This include must be declared before everything else because
|
||||
// of boost/Qt/LyX clash...
|
||||
#include "GuiImplementation.h"
|
||||
|
||||
#include "GuiView.h"
|
||||
|
||||
#include "GuiImplementation.h"
|
||||
#include "GuiWorkArea.h"
|
||||
|
||||
#include "BufferView.h"
|
||||
#include "BufferList.h"
|
||||
#include "FuncRequest.h"
|
||||
#include "LyXFunc.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
using boost::shared_ptr;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -49,7 +39,6 @@ namespace frontend {
|
||||
GuiImplementation::GuiImplementation()
|
||||
{
|
||||
view_ids_.clear();
|
||||
work_area_ids_.clear();
|
||||
}
|
||||
|
||||
|
||||
@ -74,9 +63,6 @@ bool GuiImplementation::unregisterView(int id)
|
||||
std::map<int, GuiView *>::iterator it;
|
||||
for (it = views_.begin(); it != views_.end(); ++it) {
|
||||
if (it->first == id) {
|
||||
std::vector<int> const & wa_ids = it->second->workAreaIds();
|
||||
for (size_t i = 0; i < wa_ids.size(); ++i)
|
||||
work_areas_.erase(wa_ids[i]);
|
||||
views_.erase(id);
|
||||
break;
|
||||
}
|
||||
@ -108,9 +94,7 @@ bool GuiImplementation::closeAllViews()
|
||||
}
|
||||
|
||||
views_.clear();
|
||||
work_areas_.clear();
|
||||
view_ids_.clear();
|
||||
work_area_ids_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -122,43 +106,6 @@ LyXView& GuiImplementation::view(int id) const
|
||||
}
|
||||
|
||||
|
||||
std::vector<int> const & GuiImplementation::workAreaIds()
|
||||
{
|
||||
updateIds(work_areas_, work_area_ids_);
|
||||
return work_area_ids_;
|
||||
}
|
||||
|
||||
|
||||
int GuiImplementation::newWorkArea(unsigned int w, unsigned int h, int view_id)
|
||||
{
|
||||
updateIds(views_, view_ids_);
|
||||
int id = 0;
|
||||
while (work_areas_.find(id) != work_areas_.end())
|
||||
id++;
|
||||
|
||||
GuiView * view = views_[view_id];
|
||||
|
||||
work_areas_.insert(std::pair<int, GuiWorkArea *>
|
||||
(id, new GuiWorkArea(w, h, id, *view)));
|
||||
|
||||
// FIXME BufferView creation should be independant of WorkArea creation
|
||||
buffer_views_[id].reset(new BufferView);
|
||||
work_areas_[id]->setBufferView(buffer_views_[id].get());
|
||||
|
||||
view->setWorkArea(work_areas_[id]);
|
||||
view->initTab(work_areas_[id]);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
WorkArea& GuiImplementation::workArea(int id)
|
||||
{
|
||||
BOOST_ASSERT(work_areas_.find(id) != work_areas_.end());
|
||||
return *work_areas_[id];
|
||||
}
|
||||
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace lyx
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
namespace lyx {
|
||||
namespace frontend {
|
||||
|
||||
class GuiWorkArea;
|
||||
class GuiView;
|
||||
class LyXView;
|
||||
|
||||
@ -44,9 +43,6 @@ public:
|
||||
|
||||
virtual LyXView& view(int id) const;
|
||||
|
||||
virtual int newWorkArea(unsigned int width, unsigned int height, int view_id);
|
||||
virtual WorkArea& workArea(int id);
|
||||
|
||||
private:
|
||||
|
||||
/// Multiple views container.
|
||||
@ -56,22 +52,6 @@ private:
|
||||
* \sa Qt::WA_DeleteOnClose attribute.
|
||||
*/
|
||||
std::map<int, GuiView *> views_;
|
||||
|
||||
/// Multiple workareas container.
|
||||
/**
|
||||
* Warning: This must not be a smart pointer as the destruction of the
|
||||
* object is handled by Qt when its parent view is closed.
|
||||
*/
|
||||
std::map<int, GuiWorkArea *> work_areas_;
|
||||
///
|
||||
|
||||
/// view of a buffer. Eventually there will be several.
|
||||
std::map<int, boost::shared_ptr<BufferView> > buffer_views_;
|
||||
|
||||
|
||||
std::vector<int> const & workAreaIds();
|
||||
|
||||
std::vector<int> work_area_ids_;
|
||||
};
|
||||
|
||||
} // namespace frontend
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "qt_helpers.h"
|
||||
|
||||
#include "frontends/Application.h"
|
||||
#include "frontends/Dialogs.h"
|
||||
#include "frontends/Gui.h"
|
||||
#include "frontends/WorkArea.h"
|
||||
|
||||
@ -43,6 +44,7 @@
|
||||
#include "LyXRC.h"
|
||||
#include "MenuBackend.h"
|
||||
#include "Session.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QApplication>
|
||||
@ -50,17 +52,16 @@
|
||||
#include <QDesktopWidget>
|
||||
#include <QDragEnterEvent>
|
||||
#include <QDropEvent>
|
||||
#include <QHBoxLayout>
|
||||
#include <QList>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QPushButton>
|
||||
#include <QStackedWidget>
|
||||
#include <QStatusBar>
|
||||
#include <QToolBar>
|
||||
#include <QTabBar>
|
||||
#include <QTabWidget>
|
||||
#include <QUrl>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
@ -81,84 +82,59 @@ namespace {
|
||||
|
||||
int const statusbar_timer_value = 3000;
|
||||
|
||||
class TabWidget : public QWidget
|
||||
class BackgroundWidget: public QWidget
|
||||
{
|
||||
QHBoxLayout* hlayout;
|
||||
public:
|
||||
QTabBar* tabbar;
|
||||
QPushButton* closeTabButton;
|
||||
|
||||
void hideTabsIfNecessary()
|
||||
BackgroundWidget(QString const & file, QString const & text)
|
||||
{
|
||||
if (tabbar->count() > 1) {
|
||||
tabbar->show();
|
||||
closeTabButton->show();
|
||||
} else {
|
||||
tabbar->hide();
|
||||
closeTabButton->hide();
|
||||
splash_ = new QPixmap(file);
|
||||
if (!splash_) {
|
||||
lyxerr << "could not load splash screen: '" << fromqstr(file) << "'" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
QPainter pain(splash_);
|
||||
pain.setPen(QColor(255, 255, 0));
|
||||
QFont font;
|
||||
// The font used to display the version info
|
||||
font.setStyleHint(QFont::SansSerif);
|
||||
font.setWeight(QFont::Bold);
|
||||
font.setPointSize(convert<int>(lyxrc.font_sizes[Font::SIZE_LARGE]));
|
||||
pain.setFont(font);
|
||||
pain.drawText(260, 270, text);
|
||||
}
|
||||
|
||||
TabWidget(QWidget* w, bool topTabBar)
|
||||
void paintEvent(QPaintEvent * ev)
|
||||
{
|
||||
closeTabButton = new QPushButton(this);
|
||||
FileName const file = support::libFileSearch("images", "closetab", "xpm");
|
||||
if (!file.empty()) {
|
||||
QPixmap pm(toqstr(file.absFilename()));
|
||||
closeTabButton->setIcon(QIcon(pm));
|
||||
closeTabButton->setMaximumSize(pm.size());
|
||||
closeTabButton->setFlat(true);
|
||||
} else {
|
||||
closeTabButton->setText("Close");
|
||||
}
|
||||
closeTabButton->setCursor(Qt::ArrowCursor);
|
||||
closeTabButton->setToolTip(tr("Close tab"));
|
||||
closeTabButton->setEnabled(true);
|
||||
if (!splash_)
|
||||
return;
|
||||
|
||||
tabbar = new QTabBar;
|
||||
#if QT_VERSION >= 0x040200
|
||||
tabbar->setUsesScrollButtons(true);
|
||||
#endif
|
||||
hlayout = new QHBoxLayout;
|
||||
QVBoxLayout* vlayout = new QVBoxLayout;
|
||||
hlayout->addWidget(tabbar);
|
||||
hlayout->addWidget(closeTabButton);
|
||||
if (topTabBar) {
|
||||
vlayout->addLayout(hlayout);
|
||||
vlayout->addWidget(w);
|
||||
} else {
|
||||
tabbar->setShape(QTabBar::RoundedSouth);
|
||||
vlayout->addWidget(w);
|
||||
vlayout->addLayout(hlayout);
|
||||
}
|
||||
vlayout->setMargin(0);
|
||||
vlayout->setSpacing(0);
|
||||
hlayout->setMargin(0);
|
||||
setLayout(vlayout);
|
||||
hideTabsIfNecessary();
|
||||
int x = (width() - splash_->width()) / 2;
|
||||
int y = (height() - splash_->height()) / 2;
|
||||
QPainter pain(this);
|
||||
pain.drawPixmap(x, y, *splash_);
|
||||
}
|
||||
|
||||
void clearTabbar()
|
||||
{
|
||||
for (int i = tabbar->count() - 1; i >= 0; --i)
|
||||
tabbar->removeTab(i);
|
||||
}
|
||||
private:
|
||||
QPixmap * splash_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
struct GuiView::GuiViewPrivate
|
||||
{
|
||||
vector<string> tabnames;
|
||||
string cur_title;
|
||||
|
||||
TabWidget* tabWidget;
|
||||
|
||||
int posx_offset;
|
||||
int posy_offset;
|
||||
|
||||
GuiViewPrivate() : tabWidget(0), posx_offset(0), posy_offset(0)
|
||||
QTabWidget * tab_widget_;
|
||||
QStackedWidget * stack_widget_;
|
||||
BackgroundWidget * bg_widget_;
|
||||
|
||||
GuiViewPrivate() : posx_offset(0), posy_offset(0)
|
||||
{}
|
||||
|
||||
unsigned int smallIconSize;
|
||||
@ -201,6 +177,28 @@ struct GuiView::GuiViewPrivate
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
void initBackground()
|
||||
{
|
||||
bg_widget_ = 0;
|
||||
LYXERR(Debug::GUI) << "show banner: " << lyxrc.show_banner << endl;
|
||||
/// The text to be written on top of the pixmap
|
||||
QString const text = lyx_version ? QString(lyx_version) : qt_("unknown version");
|
||||
FileName const file = support::libFileSearch("images", "banner", "png");
|
||||
if (file.empty())
|
||||
return;
|
||||
|
||||
bg_widget_ = new BackgroundWidget(toqstr(file.absFilename()), text);
|
||||
}
|
||||
|
||||
void setBackground()
|
||||
{
|
||||
if (!bg_widget_)
|
||||
return;
|
||||
|
||||
stack_widget_->setCurrentWidget(bg_widget_);
|
||||
bg_widget_->setUpdatesEnabled(true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -228,6 +226,44 @@ GuiView::GuiView(int id)
|
||||
setWindowIcon(QPixmap(toqstr(iconname.absFilename())));
|
||||
#endif
|
||||
|
||||
d.tab_widget_ = new QTabWidget;
|
||||
|
||||
QPushButton * closeTabButton = new QPushButton(this);
|
||||
FileName const file = support::libFileSearch("images", "closetab", "xpm");
|
||||
if (!file.empty()) {
|
||||
QPixmap pm(toqstr(file.absFilename()));
|
||||
closeTabButton->setIcon(QIcon(pm));
|
||||
closeTabButton->setMaximumSize(pm.size());
|
||||
closeTabButton->setFlat(true);
|
||||
} else {
|
||||
closeTabButton->setText("Close");
|
||||
}
|
||||
closeTabButton->setCursor(Qt::ArrowCursor);
|
||||
closeTabButton->setToolTip(tr("Close tab"));
|
||||
closeTabButton->setEnabled(true);
|
||||
|
||||
QObject::connect(d.tab_widget_, SIGNAL(currentChanged(int)),
|
||||
this, SLOT(currentTabChanged(int)));
|
||||
QObject::connect(closeTabButton, SIGNAL(clicked()),
|
||||
this, SLOT(closeCurrentTab()));
|
||||
|
||||
d.tab_widget_->setCornerWidget(closeTabButton);
|
||||
#if QT_VERSION >= 0x040200
|
||||
d.tab_widget_->setUsesScrollButtons(true);
|
||||
#endif
|
||||
|
||||
d.initBackground();
|
||||
if (d.bg_widget_) {
|
||||
lyxerr << "stack widget!" << endl;
|
||||
d.stack_widget_ = new QStackedWidget;
|
||||
d.stack_widget_->addWidget(d.bg_widget_);
|
||||
d.stack_widget_->addWidget(d.tab_widget_);
|
||||
setCentralWidget(d.stack_widget_);
|
||||
} else {
|
||||
d.stack_widget_ = 0;
|
||||
setCentralWidget(d.tab_widget_);
|
||||
}
|
||||
|
||||
// For Drag&Drop.
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
@ -250,8 +286,8 @@ void GuiView::close()
|
||||
|
||||
void GuiView::setFocus()
|
||||
{
|
||||
BOOST_ASSERT(work_area_);
|
||||
static_cast<GuiWorkArea *>(work_area_)->setFocus();
|
||||
if (d.tab_widget_->count())
|
||||
d.tab_widget_->currentWidget()->setFocus();
|
||||
}
|
||||
|
||||
|
||||
@ -274,14 +310,8 @@ void GuiView::init()
|
||||
QObject::connect(&statusbar_timer_, SIGNAL(timeout()),
|
||||
this, SLOT(update_view_state_qt()));
|
||||
|
||||
BOOST_ASSERT(work_area_);
|
||||
if (!work_area_->bufferView().buffer() && !theBufferList().empty())
|
||||
setBuffer(theBufferList().first());
|
||||
|
||||
// make sure the buttons are disabled if needed
|
||||
updateToolbars();
|
||||
updateLayoutChoice();
|
||||
updateMenubar();
|
||||
if (d.stack_widget_)
|
||||
d.stack_widget_->setCurrentWidget(d.bg_widget_);
|
||||
}
|
||||
|
||||
|
||||
@ -311,15 +341,6 @@ void GuiView::closeEvent(QCloseEvent * close_event)
|
||||
|
||||
quitting = true;
|
||||
|
||||
if (view()->buffer()) {
|
||||
// save cursor position for opened files to .lyx/session
|
||||
// only bottom (whole doc) level pit and pos is saved.
|
||||
LyX::ref().session().lastFilePos().save(
|
||||
FileName(buffer()->fileName()),
|
||||
boost::tie(view()->cursor().bottom().pit(),
|
||||
view()->cursor().bottom().pos()));
|
||||
}
|
||||
|
||||
// this is the place where we leave the frontend.
|
||||
// it is the only point at which we start quitting.
|
||||
saveGeometry();
|
||||
@ -501,7 +522,9 @@ void GuiView::setGeometry(unsigned int width,
|
||||
(void)geometryArg;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
d.setBackground();
|
||||
|
||||
show();
|
||||
|
||||
// For an unknown reason, the Window title update is not effective for
|
||||
@ -610,56 +633,6 @@ void GuiView::update_view_state_qt()
|
||||
}
|
||||
|
||||
|
||||
void GuiView::initTab(QWidget* workarea)
|
||||
{
|
||||
// construct the TabWidget with 'false' to have the tabbar at the bottom
|
||||
d.tabWidget = new TabWidget(workarea, true);
|
||||
setCentralWidget(d.tabWidget);
|
||||
QObject::connect(d.tabWidget->tabbar, SIGNAL(currentChanged(int)),
|
||||
this, SLOT(currentTabChanged(int)));
|
||||
QObject::connect(d.tabWidget->closeTabButton, SIGNAL(clicked()),
|
||||
this, SLOT(closeCurrentTab()));
|
||||
}
|
||||
|
||||
|
||||
void GuiView::updateTab()
|
||||
{
|
||||
std::vector<string> const & names = theBufferList().getFileNames();
|
||||
|
||||
string cur_title;
|
||||
if (view()->buffer()) {
|
||||
cur_title = view()->buffer()->fileName();
|
||||
}
|
||||
|
||||
// avoid unnecessary tabbar rebuild:
|
||||
// check if something has changed
|
||||
if (d.tabnames == names && d.cur_title == cur_title)
|
||||
return;
|
||||
d.tabnames = names;
|
||||
d.cur_title = cur_title;
|
||||
|
||||
QTabBar & tabbar = *d.tabWidget->tabbar;
|
||||
|
||||
// update when all is done
|
||||
tabbar.blockSignals(true);
|
||||
|
||||
// remove all tab bars
|
||||
d.tabWidget->clearTabbar();
|
||||
|
||||
// rebuild tabbar and function map from scratch
|
||||
if (names.size() > 1) {
|
||||
for(size_t i = 0; i < names.size(); i++) {
|
||||
tabbar.addTab(toqstr(makeDisplayPath(names[i], 30)));
|
||||
// set current tab
|
||||
if (names[i] == cur_title)
|
||||
tabbar.setCurrentIndex(i);
|
||||
}
|
||||
}
|
||||
tabbar.blockSignals(false);
|
||||
d.tabWidget->hideTabsIfNecessary();
|
||||
}
|
||||
|
||||
|
||||
void GuiView::closeCurrentTab()
|
||||
{
|
||||
dispatch(FuncRequest(LFUN_BUFFER_CLOSE));
|
||||
@ -668,8 +641,32 @@ void GuiView::closeCurrentTab()
|
||||
|
||||
void GuiView::currentTabChanged(int i)
|
||||
{
|
||||
BOOST_ASSERT(i >= 0 && size_type(i) < d.tabnames.size());
|
||||
dispatch(FuncRequest(LFUN_BUFFER_SWITCH, d.tabnames[i]));
|
||||
disconnectBuffer();
|
||||
disconnectBufferView();
|
||||
GuiWorkArea * wa = dynamic_cast<GuiWorkArea *>(d.tab_widget_->widget(i));
|
||||
BOOST_ASSERT(wa);
|
||||
BufferView & bv = wa->bufferView();
|
||||
connectBufferView(bv);
|
||||
connectBuffer(*bv.buffer());
|
||||
bv.updateMetrics(false);
|
||||
bv.cursor().fixIfBroken();
|
||||
wa->setUpdatesEnabled(true);
|
||||
wa->redraw();
|
||||
wa->setFocus();
|
||||
|
||||
updateToc();
|
||||
// Buffer-dependent dialogs should be updated or
|
||||
// hidden. This should go here because some dialogs (eg ToC)
|
||||
// require bv_->text.
|
||||
getDialogs().updateBufferDependent(true);
|
||||
updateMenubar();
|
||||
updateToolbars();
|
||||
updateLayoutChoice();
|
||||
updateWindowTitle();
|
||||
updateStatusBar();
|
||||
|
||||
lyxerr << "currentTabChanged " << i
|
||||
<< "File" << wa->bufferView().buffer()->fileName() << endl;
|
||||
}
|
||||
|
||||
|
||||
@ -741,11 +738,18 @@ bool GuiView::event(QEvent * e)
|
||||
|
||||
case QEvent::ShortcutOverride: {
|
||||
QKeyEvent * ke = static_cast<QKeyEvent*>(e);
|
||||
if (d.tab_widget_->count() == 0) {
|
||||
theLyXFunc().setLyXView(this);
|
||||
boost::shared_ptr<QKeySymbol> sym(new QKeySymbol);
|
||||
sym->set(ke);
|
||||
theLyXFunc().processKeySym(sym, q_key_state(ke->modifiers()));
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
if (ke->key() == Qt::Key_Tab || ke->key() == Qt::Key_Backtab) {
|
||||
boost::shared_ptr<QKeySymbol> sym(new QKeySymbol);
|
||||
sym->set(ke);
|
||||
BOOST_ASSERT(work_area_);
|
||||
work_area_->processKeySym(sym, key_modifier::none);
|
||||
currentWorkArea()->processKeySym(sym, key_modifier::none);
|
||||
e->accept();
|
||||
return true;
|
||||
}
|
||||
@ -773,17 +777,20 @@ void GuiView::show()
|
||||
|
||||
void GuiView::busy(bool yes)
|
||||
{
|
||||
BOOST_ASSERT(work_area_);
|
||||
static_cast<GuiWorkArea *>(work_area_)->setUpdatesEnabled(!yes);
|
||||
if (d.tab_widget_->count()) {
|
||||
GuiWorkArea * wa = dynamic_cast<GuiWorkArea *>(d.tab_widget_->currentWidget());
|
||||
BOOST_ASSERT(wa);
|
||||
wa->setUpdatesEnabled(!yes);
|
||||
if (yes)
|
||||
wa->stopBlinkingCursor();
|
||||
else
|
||||
wa->startBlinkingCursor();
|
||||
}
|
||||
|
||||
if (yes) {
|
||||
work_area_->stopBlinkingCursor();
|
||||
if (yes)
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
}
|
||||
else {
|
||||
work_area_->startBlinkingCursor();
|
||||
else
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -833,6 +840,96 @@ Toolbars::ToolbarPtr GuiView::makeToolbar(ToolbarInfo const & tbinfo, bool newli
|
||||
return Toolbars::ToolbarPtr(Tb);
|
||||
}
|
||||
|
||||
|
||||
WorkArea * GuiView::workArea(Buffer & buffer)
|
||||
{
|
||||
for (int i = 0; i != d.tab_widget_->count(); ++i) {
|
||||
GuiWorkArea * wa = dynamic_cast<GuiWorkArea *>(d.tab_widget_->widget(i));
|
||||
BOOST_ASSERT(wa);
|
||||
if (wa->bufferView().buffer() == &buffer)
|
||||
return wa;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
WorkArea * GuiView::addWorkArea(Buffer & buffer)
|
||||
{
|
||||
GuiWorkArea * wa = new GuiWorkArea(buffer, *this);
|
||||
d.tab_widget_->addTab(wa, toqstr(makeDisplayPath(buffer.fileName(), 30)));
|
||||
wa->bufferView().updateMetrics(false);
|
||||
if (d.stack_widget_)
|
||||
d.stack_widget_->setCurrentWidget(d.tab_widget_);
|
||||
return wa;
|
||||
}
|
||||
|
||||
|
||||
WorkArea * GuiView::currentWorkArea()
|
||||
{
|
||||
if (d.tab_widget_->count() == 0)
|
||||
return 0;
|
||||
BOOST_ASSERT(dynamic_cast<GuiWorkArea *>(d.tab_widget_->currentWidget()));
|
||||
return dynamic_cast<GuiWorkArea *>(d.tab_widget_->currentWidget());
|
||||
}
|
||||
|
||||
|
||||
WorkArea const * GuiView::currentWorkArea() const
|
||||
{
|
||||
if (d.tab_widget_->count() == 0)
|
||||
return 0;
|
||||
BOOST_ASSERT(dynamic_cast<GuiWorkArea const *>(d.tab_widget_->currentWidget()));
|
||||
return dynamic_cast<GuiWorkArea const *>(d.tab_widget_->currentWidget());
|
||||
}
|
||||
|
||||
|
||||
void GuiView::setCurrentWorkArea(WorkArea * work_area)
|
||||
{
|
||||
BOOST_ASSERT(work_area);
|
||||
|
||||
// Changing work area can result from opening a file so
|
||||
// update the toc in any case.
|
||||
updateToc();
|
||||
|
||||
GuiWorkArea * wa = dynamic_cast<GuiWorkArea *>(work_area);
|
||||
BOOST_ASSERT(wa);
|
||||
d.tab_widget_->setCurrentWidget(wa);
|
||||
wa->setFocus();
|
||||
}
|
||||
|
||||
|
||||
void GuiView::removeWorkArea(WorkArea * work_area)
|
||||
{
|
||||
BOOST_ASSERT(work_area);
|
||||
if (work_area == currentWorkArea()) {
|
||||
disconnectBuffer();
|
||||
disconnectBufferView();
|
||||
}
|
||||
|
||||
// removing a work area often results from closing a file so
|
||||
// update the toc in any case.
|
||||
updateToc();
|
||||
|
||||
GuiWorkArea * gwa = dynamic_cast<GuiWorkArea *>(work_area);
|
||||
BOOST_ASSERT(gwa);
|
||||
int index = d.tab_widget_->indexOf(gwa);
|
||||
d.tab_widget_->removeTab(index);
|
||||
|
||||
delete gwa;
|
||||
|
||||
if (d.tab_widget_->count()) {
|
||||
// make sure the next work area is enabled.
|
||||
d.tab_widget_->currentWidget()->setUpdatesEnabled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
getDialogs().hideBufferDependent();
|
||||
if (d.stack_widget_) {
|
||||
// No more work area, switch to the background widget.
|
||||
d.setBackground();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace frontend
|
||||
} // namespace lyx
|
||||
|
||||
|
@ -75,8 +75,6 @@ public:
|
||||
virtual void clearMessage();
|
||||
virtual bool hasFocus() const;
|
||||
|
||||
virtual void updateTab();
|
||||
|
||||
/// show - display the top-level window
|
||||
void show();
|
||||
|
||||
@ -86,8 +84,6 @@ public:
|
||||
/// menu item has been selected
|
||||
void activated(FuncRequest const &);
|
||||
|
||||
void initTab(QWidget* workArea);
|
||||
|
||||
QMenu* createPopupMenu();
|
||||
|
||||
Q_SIGNALS:
|
||||
@ -118,6 +114,19 @@ protected:
|
||||
///
|
||||
virtual void moveEvent(QMoveEvent * e);
|
||||
|
||||
/// \return the \c Workarea associated to \p Buffer
|
||||
/// \retval 0 if no \c WorkArea is found.
|
||||
WorkArea * workArea(Buffer & buffer);
|
||||
|
||||
/// Add a \c WorkArea
|
||||
/// \return the \c Workarea associated to \p Buffer
|
||||
/// \retval 0 if no \c WorkArea is found.
|
||||
WorkArea * addWorkArea(Buffer & buffer);
|
||||
void setCurrentWorkArea(WorkArea * work_area);
|
||||
void removeWorkArea(WorkArea * work_area);
|
||||
WorkArea const * currentWorkArea() const;
|
||||
WorkArea * currentWorkArea();
|
||||
|
||||
private:
|
||||
///
|
||||
void dragEnterEvent(QDragEnterEvent * ev);
|
||||
|
@ -173,8 +173,8 @@ SyntheticMouseEvent::SyntheticMouseEvent()
|
||||
{}
|
||||
|
||||
|
||||
GuiWorkArea::GuiWorkArea(int w, int h, int id, LyXView & lyx_view)
|
||||
: WorkArea(id, lyx_view), need_resize_(false), schedule_redraw_(false),
|
||||
GuiWorkArea::GuiWorkArea(Buffer & buf, LyXView & lv)
|
||||
: WorkArea(buf, lv), need_resize_(false), schedule_redraw_(false),
|
||||
preedit_lines_(1)
|
||||
{
|
||||
screen_ = QPixmap(viewport()->width(), viewport()->height());
|
||||
@ -196,8 +196,6 @@ GuiWorkArea::GuiWorkArea(int w, int h, int id, LyXView & lyx_view)
|
||||
|
||||
viewport()->setCursor(Qt::IBeamCursor);
|
||||
|
||||
resize(w, h);
|
||||
|
||||
synthetic_mouse_event_.timeout.timeout.connect(
|
||||
boost::bind(&GuiWorkArea::generateSyntheticMouseEvent,
|
||||
this));
|
||||
@ -258,17 +256,13 @@ void GuiWorkArea::focusInEvent(QFocusEvent * /*event*/)
|
||||
// if (theApp() == 0 || &lyx_view_ == theApp()->currentView())
|
||||
// return;
|
||||
|
||||
theApp()->setCurrentView(lyx_view_);
|
||||
theApp()->setCurrentView(*lyx_view_);
|
||||
|
||||
// Repaint the whole screen.
|
||||
// Note: this is different from redraw() as only the backing pixmap
|
||||
// will be redrawn, which is cheap.
|
||||
viewport()->repaint();
|
||||
|
||||
// FIXME: it would be better to send a signal "newBuffer()"
|
||||
// in BufferList that could be connected to the different tabbars.
|
||||
lyx_view_.updateTab();
|
||||
|
||||
startBlinkingCursor();
|
||||
}
|
||||
|
||||
@ -459,49 +453,6 @@ void GuiWorkArea::update(int x, int y, int w, int h)
|
||||
}
|
||||
|
||||
|
||||
void GuiWorkArea::doGreyOut(QLPainter & pain)
|
||||
{
|
||||
pain.fillRectangle(0, 0, width(), height(),
|
||||
Color::bottomarea);
|
||||
|
||||
//if (!lyxrc.show_banner)
|
||||
// return;
|
||||
LYXERR(Debug::GUI) << "show banner: " << lyxrc.show_banner << endl;
|
||||
/// The text to be written on top of the pixmap
|
||||
QString const text = lyx_version ? QString(lyx_version) : qt_("unknown version");
|
||||
FileName const file = support::libFileSearch("images", "banner", "png");
|
||||
if (file.empty())
|
||||
return;
|
||||
|
||||
QPixmap pm(toqstr(file.absFilename()));
|
||||
if (!pm) {
|
||||
lyxerr << "could not load splash screen: '" << file << "'" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
QFont font;
|
||||
// The font used to display the version info
|
||||
font.setStyleHint(QFont::SansSerif);
|
||||
font.setWeight(QFont::Bold);
|
||||
font.setPointSize(convert<int>(lyxrc.font_sizes[Font::SIZE_LARGE]));
|
||||
|
||||
int const w = pm.width();
|
||||
int const h = pm.height();
|
||||
|
||||
int x = (width() - w) / 2;
|
||||
int y = (height() - h) / 2;
|
||||
|
||||
pain.drawPixmap(x, y, pm);
|
||||
|
||||
x += 260;
|
||||
y += 270;
|
||||
|
||||
pain.setPen(QColor(255, 255, 0));
|
||||
pain.setFont(font);
|
||||
pain.drawText(x, y, text);
|
||||
}
|
||||
|
||||
|
||||
void GuiWorkArea::paintEvent(QPaintEvent * ev)
|
||||
{
|
||||
QRect const rc = ev->rect();
|
||||
@ -538,14 +489,6 @@ void GuiWorkArea::expose(int x, int y, int w, int h)
|
||||
void GuiWorkArea::updateScreen()
|
||||
{
|
||||
QLPainter pain(&screen_);
|
||||
|
||||
if (greyed_out_) {
|
||||
LYXERR(Debug::GUI) << "splash screen requested" << endl;
|
||||
verticalScrollBar()->hide();
|
||||
doGreyOut(pain);
|
||||
return;
|
||||
}
|
||||
|
||||
verticalScrollBar()->show();
|
||||
paintText(*buffer_view_, pain);
|
||||
}
|
||||
@ -554,11 +497,9 @@ void GuiWorkArea::updateScreen()
|
||||
void GuiWorkArea::showCursor(int x, int y, int h, CursorShape shape)
|
||||
{
|
||||
if (schedule_redraw_) {
|
||||
if (buffer_view_ && buffer_view_->buffer()) {
|
||||
buffer_view_->update(Update::Force);
|
||||
updateScreen();
|
||||
viewport()->update(QRect(0, 0, viewport()->width(), viewport()->height()));
|
||||
}
|
||||
buffer_view_->update(Update::Force);
|
||||
updateScreen();
|
||||
viewport()->update(QRect(0, 0, viewport()->width(), viewport()->height()));
|
||||
schedule_redraw_ = false;
|
||||
// Show the cursor immediately after the update.
|
||||
hideCursor();
|
||||
@ -586,11 +527,6 @@ void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
|
||||
docstring const & preedit_string
|
||||
= qstring_to_ucs4(e->preeditString());
|
||||
|
||||
if(greyed_out_) {
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!commit_string.isEmpty()) {
|
||||
|
||||
LYXERR(Debug::KEY) << BOOST_CURRENT_FUNCTION
|
||||
|
@ -88,10 +88,11 @@ class GuiWorkArea : public QAbstractScrollArea, public WorkArea
|
||||
|
||||
public:
|
||||
///
|
||||
GuiWorkArea(int width, int height, int id, LyXView & lyx_view);
|
||||
GuiWorkArea(Buffer & buffer, LyXView & lv);
|
||||
|
||||
///
|
||||
bool hasFocus() const { return QAbstractScrollArea::hasFocus(); }
|
||||
bool isVisible() const { return QAbstractScrollArea::isVisible(); }
|
||||
|
||||
/// return the width of the content pane
|
||||
virtual int width() const { return viewport()->width(); }
|
||||
|
@ -386,37 +386,34 @@ Buffer * getChildBuffer(Buffer const & buffer, InsetCommandParams const & params
|
||||
|
||||
} // namespace anon
|
||||
|
||||
|
||||
Buffer * loadIfNeeded(Buffer const & buffer, InsetCommandParams const & params)
|
||||
/// return true if the file is or got loaded.
|
||||
Buffer * loadIfNeeded(Buffer const & parent, InsetCommandParams const & params)
|
||||
{
|
||||
if (isVerbatim(params) || isListings(params))
|
||||
return 0;
|
||||
|
||||
FileName const included_file = includedFilename(buffer, params);
|
||||
string const parent_filename = parent.fileName();
|
||||
FileName const included_file = makeAbsPath(to_utf8(params["filename"]),
|
||||
onlyPath(parent_filename));
|
||||
|
||||
if (!isLyXFilename(included_file.absFilename()))
|
||||
return 0;
|
||||
|
||||
Buffer * buf = theBufferList().getBuffer(included_file.absFilename());
|
||||
if (!buf) {
|
||||
Buffer * child = theBufferList().getBuffer(included_file.absFilename());
|
||||
if (!child) {
|
||||
// the readonly flag can/will be wrong, not anymore I think.
|
||||
if (!fs::exists(included_file.toFilesystemEncoding()))
|
||||
return false;
|
||||
if (use_gui) {
|
||||
lyx::dispatch(FuncRequest(LFUN_BUFFER_CHILD_OPEN,
|
||||
included_file.absFilename() + "|true"));
|
||||
buf = theBufferList().getBuffer(included_file.absFilename());
|
||||
}
|
||||
else {
|
||||
buf = theBufferList().newBuffer(included_file.absFilename());
|
||||
if (!loadLyXFile(buf, included_file)) {
|
||||
//close the buffer we just opened
|
||||
theBufferList().close(buf, false);
|
||||
return false;
|
||||
}
|
||||
return 0;
|
||||
|
||||
child = theBufferList().newBuffer(included_file.absFilename());
|
||||
if (!loadLyXFile(child, included_file)) {
|
||||
//close the buffer we just opened
|
||||
theBufferList().close(child, false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
buf->setParentName(parentFilename(buffer));
|
||||
return buf;
|
||||
child->setParentName(parent_filename);
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
@ -768,7 +765,7 @@ InsetInclude::getBibfilesCache(Buffer const & buffer) const
|
||||
|
||||
bool InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const
|
||||
{
|
||||
BOOST_ASSERT(mi.base.bv && mi.base.bv->buffer());
|
||||
BOOST_ASSERT(mi.base.bv);
|
||||
|
||||
bool use_preview = false;
|
||||
if (RenderPreview::status() != LyXRC::PREVIEW_OFF) {
|
||||
@ -801,7 +798,7 @@ void InsetInclude::draw(PainterInfo & pi, int x, int y) const
|
||||
{
|
||||
setPosCache(pi, x, y);
|
||||
|
||||
BOOST_ASSERT(pi.base.bv && pi.base.bv->buffer());
|
||||
BOOST_ASSERT(pi.base.bv);
|
||||
|
||||
bool use_preview = false;
|
||||
if (RenderPreview::status() != LyXRC::PREVIEW_OFF) {
|
||||
|
Loading…
Reference in New Issue
Block a user