#include "graphics/GraphicsImage.h"
#include "graphics/GraphicsLoader.h"
+#include "support/convert.h"
#include "support/debug.h"
#include "support/gettext.h"
#include "support/FileName.h"
// cursor is at the top or bottom edge of the viewport. One scroll per 0.2 s
SyntheticMouseEvent::SyntheticMouseEvent()
: timeout(200), restart_timeout(true),
- x_old(-1), y_old(-1), scrollbar_value_old(-1.0)
+ x_old(-1), y_old(-1), min_scrollbar_old(-1), max_scrollbar_old(-1)
{}
: buffer_view_(0), lyx_view_(0),
cursor_visible_(false),
need_resize_(false), schedule_redraw_(false),
- preedit_lines_(1), completer_(new GuiCompleter(this))
+ preedit_lines_(1), completer_(new GuiCompleter(this, this)),
+ context_target_pos_()
{
}
GuiWorkArea::GuiWorkArea(Buffer & buffer, GuiView & gv)
- : buffer_view_(0), lyx_view_(0),
+ : buffer_view_(0), read_only_(buffer.isReadonly()), lyx_view_(0),
cursor_visible_(false),
need_resize_(false), schedule_redraw_(false),
- preedit_lines_(1), completer_(new GuiCompleter(this))
+ preedit_lines_(1), completer_(new GuiCompleter(this, this)),
+ context_target_pos_()
{
setGuiView(gv);
setBuffer(buffer);
}
screen_ = QPixmap(viewport()->width(), viewport()->height());
+ // With Qt4.5 a mouse event will happen before the first paint event
+ // so make sure that the buffer view has an up to date metrics.
+ buffer_view_->resize(viewport()->width(), viewport()->height());
cursor_ = new frontend::CursorWidget();
cursor_->hide();
setAcceptDrops(true);
setMouseTracking(true);
setMinimumSize(100, 70);
-#ifdef Q_WS_MACX
setFrameStyle(QFrame::NoFrame);
-#else
- setFrameStyle(QFrame::Box);
-#endif
updateWindowTitle();
viewport()->setAutoFillBackground(false);
delete buffer_view_;
delete cursor_;
// Completer has a QObject parent and is thus automatically destroyed.
+ // See #4758.
// delete completer_;
}
void GuiWorkArea::setBuffer(Buffer & buffer)
{
delete buffer_view_;
- buffer_view_ = new BufferView(buffer),
+ buffer_view_ = new BufferView(buffer);
buffer.workAreaManager().add(this);
// HACK: Prevents an additional redraw when the scrollbar pops up
void GuiWorkArea::setFullScreen(bool full_screen)
{
buffer_view_->setFullScreen(full_screen);
+ setFrameStyle(QFrame::NoFrame);
if (full_screen) {
setFrameStyle(QFrame::NoFrame);
if (lyxrc.full_screen_scrollbar)
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- } else {
-#ifdef Q_WS_MACX
- setFrameStyle(QFrame::NoFrame);
-#else
- setFrameStyle(QFrame::Box);
-#endif
+ } else
setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- }
}
}
-void GuiWorkArea::redraw()
+void GuiWorkArea::redraw(bool update_metrics)
{
if (!isVisible())
// No need to redraw in this case.
// No need to do anything if this is the current view. The BufferView
// metrics are already up to date.
- if (lyx_view_ != guiApp->currentView()
+ if (update_metrics || lyx_view_ != guiApp->currentView()
|| lyx_view_->currentWorkArea() != this) {
// FIXME: it would be nice to optimize for the off-screen case.
buffer_view_->updateMetrics();
if (lyxerr.debugging(Debug::WORKAREA))
buffer_view_->coordCache().dump();
+
+ setReadOnly(buffer_view_->buffer().isReadonly());
}
void GuiWorkArea::processKeySym(KeySymbol const & key, KeyModifier mod)
{
- if (lyx_view_->isFullScreen() && lyx_view_->menuBar()->isVisible()) {
+ if (lyx_view_->isFullScreen() && lyx_view_->menuBar()->isVisible()
+ && lyxrc.full_screen_menubar) {
// FIXME HACK: we should not have to do this here. See related comment
// in GuiView::event() (QEvent::ShortcutOverride)
lyx_view_->menuBar()->hide();
// we better stop the blinking cursor...
// the cursor gets restarted in GuiView::restartCursor()
stopBlinkingCursor();
-
- theLyXFunc().setLyXView(lyx_view_);
- theLyXFunc().processKeySym(key, mod);
+ guiApp->processKeySym(key, mod);
}
{
// Handle drag&drop
if (cmd0.action == LFUN_FILE_OPEN) {
- lyx_view_->dispatch(cmd0);
+ DispatchResult dr;
+ lyx_view_->dispatch(cmd0, dr);
return;
}
- theLyXFunc().setLyXView(lyx_view_);
-
FuncRequest cmd;
if (cmd0.action == LFUN_MOUSE_PRESS) {
// WARNING: Please don't put any code that will trigger a repaint here!
// We are already inside a paint event.
lyx_view_->setBusy(true);
+ Point p;
+ int h = 0;
+ buffer_view_->cursorPosAndHeight(p, h);
+ bool const cursor_in_view = buffer_view_->cursorInView(p, h);
buffer_view_->resize(viewport()->width(), viewport()->height());
+ if (cursor_in_view)
+ buffer_view_->scrollToCursor();
updateScreen();
// Update scrollbars which might have changed due different
if (realfont.language() == latex_language)
l_shape = false;
- Font const font = buffer_view_->cursor().getFont();
- FontMetrics const & fm = theFontMetrics(font);
- int const asc = fm.maxAscent();
- int const des = fm.maxDescent();
- int h = asc + des;
- int x = 0;
- int y = 0;
- Cursor & cur = buffer_view_->cursor();
- cur.getPos(x, y);
- y -= asc;
-
- // if it doesn't touch the screen, don't try to show it
- bool cursorInView = true;
- if (y + h < 0 || y >= viewport()->height()
- || !cur.bv().paragraphVisible(cur))
- cursorInView = false;
-
+ Point p;
+ int h = 0;
+ buffer_view_->cursorPosAndHeight(p, h);
// show cursor on screen
+ Cursor & cur = buffer_view_->cursor();
bool completable = cur.inset().showCompletionCursor()
&& completer_->completionAvailable()
&& !completer_->popupVisible()
&& !completer_->inlineVisible();
- if (cursorInView) {
+ if (buffer_view_->cursorInView(p, h)) {
cursor_visible_ = true;
- showCursor(x, y, h, l_shape, isrtl, completable);
+ showCursor(p.x_, p.y_, h, l_shape, isrtl, completable);
}
}
void GuiWorkArea::contextMenuEvent(QContextMenuEvent * e)
{
- QPoint pos = e->pos();
+ QPoint pos;
+ if (e->reason() == QContextMenuEvent::Mouse)
+ // the position is set on mouse press
+ pos = context_target_pos_;
+ else
+ pos = e->pos();
+ Cursor const & cur = buffer_view_->cursor();
+ if (e->reason() == QContextMenuEvent::Keyboard && cur.inTexted()) {
+ // Do not access the context menu of math right in front of before
+ // the cursor. This does not work when the cursor is in text.
+ Inset * inset = cur.paragraph().getInset(cur.pos());
+ if (inset && inset->asInsetMath())
+ --pos.rx();
+ else if (cur.pos() > 0) {
+ Inset * inset = cur.paragraph().getInset(cur.pos() - 1);
+ if (inset)
+ ++pos.rx();
+ }
+ }
docstring name = buffer_view_->contextMenu(pos.x(), pos.y());
if (name.empty()) {
QAbstractScrollArea::contextMenuEvent(e);
void GuiWorkArea::focusInEvent(QFocusEvent * e)
{
- /*
- LYXERR(Debug::DEBUG, "GuiWorkArea::focusInEvent(): " << this << std::endl);
- GuiWorkArea * old_gwa = theGuiApp()->currentView()->currentWorkArea();
- if (old_gwa)
- old_gwa->stopBlinkingCursor();
- lyx_view_->setCurrentWorkArea(this);
- */
-
+ LYXERR(Debug::DEBUG, "GuiWorkArea::focusInEvent(): " << this << endl);
if (lyx_view_->currentWorkArea() != this)
lyx_view_->setCurrentWorkArea(this);
void GuiWorkArea::focusOutEvent(QFocusEvent * e)
{
- LYXERR(Debug::DEBUG, "GuiWorkArea::focusOutEvent(): " << this << std::endl);
+ LYXERR(Debug::DEBUG, "GuiWorkArea::focusOutEvent(): " << this << endl);
stopBlinkingCursor();
QAbstractScrollArea::focusOutEvent(e);
}
return;
}
+ if (e->button() == Qt::RightButton)
+ context_target_pos_ = e->pos();
+
inputContext()->reset();
FuncRequest const cmd(LFUN_MOUSE_PRESS, e->x(), e->y(),
// Has anything changed on-screen since the last QMouseEvent
// was received?
- double const scrollbar_value = verticalScrollBar()->value();
if (e->x() == synthetic_mouse_event_.x_old
&& e->y() == synthetic_mouse_event_.y_old
- && scrollbar_value == synthetic_mouse_event_.scrollbar_value_old) {
+ && synthetic_mouse_event_.min_scrollbar_old == verticalScrollBar()->minimum()
+ && synthetic_mouse_event_.max_scrollbar_old == verticalScrollBar()->maximum()) {
// Nothing changed on-screen since the last QMouseEvent.
return;
}
// Yes something has changed. Store the params used to check this.
synthetic_mouse_event_.x_old = e->x();
synthetic_mouse_event_.y_old = e->y();
- synthetic_mouse_event_.scrollbar_value_old = scrollbar_value;
+ synthetic_mouse_event_.min_scrollbar_old = verticalScrollBar()->minimum();
+ synthetic_mouse_event_.max_scrollbar_old = verticalScrollBar()->maximum();
// ... and dispatch the event to the LyX core.
dispatch(cmd);
// documentation of QWheelEvent)
int const delta = ev->delta() / 120;
if (ev->modifiers() & Qt::ControlModifier) {
- lyxrc.zoom += 5 * delta;
- if (lyxrc.zoom < 10)
- lyxrc.zoom = 10;
- // The global QPixmapCache is used in GuiPainter to cache text
- // painting so we must reset it.
- QPixmapCache::clear();
- guiApp->fontLoader().update();
- ev->accept();
- lyx::dispatch(FuncRequest(LFUN_SCREEN_FONT_UPDATE));
+ docstring arg = convert<docstring>(5 * delta);
+ lyx::dispatch(FuncRequest(LFUN_BUFFER_ZOOM_IN, arg));
return;
}
scroll_value *= delta;
// Take into account user preference.
- scroll_value *= lyxrc.mouse_wheel_speed;
+ scroll_value = int(scroll_value * lyxrc.mouse_wheel_speed);
LYXERR(Debug::SCROLLING, "wheelScrollLines = " << lines
<< " delta = " << delta << " scroll_value = " << scroll_value
<< " page_step = " << page_step);
// Has anything changed on-screen since the last timeout signal
// was received?
- double const scrollbar_value = verticalScrollBar()->value();
- if (scrollbar_value != synthetic_mouse_event_.scrollbar_value_old) {
- // Yes it has. Store the params used to check this.
- synthetic_mouse_event_.scrollbar_value_old = scrollbar_value;
-
- // ... and dispatch the event to the LyX core.
- dispatch(synthetic_mouse_event_.cmd);
+ int const min_scrollbar = verticalScrollBar()->minimum();
+ int const max_scrollbar = verticalScrollBar()->maximum();
+ if (min_scrollbar == synthetic_mouse_event_.min_scrollbar_old
+ && max_scrollbar == synthetic_mouse_event_.max_scrollbar_old) {
+ return;
}
+ // Yes it has. Store the params used to check this.
+ synthetic_mouse_event_.min_scrollbar_old = min_scrollbar;
+ synthetic_mouse_event_.max_scrollbar_old = max_scrollbar;
+ // ... and dispatch the event to the LyX core.
+ dispatch(synthetic_mouse_event_.cmd);
}
KeySymbol sym;
setKeySymbol(&sym, ev);
- processKeySym(sym, q_key_state(ev->modifiers()));
- ev->accept();
+ if (sym.isOK()) {
+ processKeySym(sym, q_key_state(ev->modifiers()));
+ ev->accept();
+ } else {
+ ev->ignore();
+ }
}
if (need_resize_) {
screen_ = QPixmap(viewport()->width(), viewport()->height());
resizeBufferView();
- hideCursor();
- showCursor();
+ if (cursor_visible_) {
+ hideCursor();
+ showCursor();
+ }
}
QPainter pain(viewport());
{
QRect cur_r(0, 0, 0, 0);
switch (query) {
- // this is the CJK-specific composition window position.
+ // this is the CJK-specific composition window position and
+ // the context menu position when the menu key is pressed.
case Qt::ImMicroFocus:
cur_r = cursor_->rect();
if (preedit_lines_ != 1)
cur_r.moveLeft(10);
- cur_r.moveBottom(cur_r.bottom() + cur_r.height() * preedit_lines_);
+ cur_r.moveBottom(cur_r.bottom()
+ + cur_r.height() * (preedit_lines_ - 1));
// return lower right of cursor in LyX.
return cur_r;
default:
if (!fileName.empty()) {
maximize_title = fileName.displayName(30);
minimize_title = from_utf8(fileName.onlyFileName());
- if (buf.lyxvc().inUse())
- maximize_title += _(" (version control)");
+ if (buf.lyxvc().inUse()) {
+ if (buf.lyxvc().locker().empty())
+ maximize_title += _(" (version control)");
+ else
+ maximize_title += _(" (version control, locking)");
+ }
if (!buf.isClean()) {
maximize_title += _(" (changed)");
minimize_title += char_type('*');
}
-void GuiWorkArea::setReadOnly(bool)
+void GuiWorkArea::setReadOnly(bool read_only)
{
+ if (read_only_ == read_only)
+ return;
+ read_only_ = read_only;
updateWindowTitle();
if (this == lyx_view_->currentWorkArea())
lyx_view_->updateDialogs();
////////////////////////////////////////////////////////////////////
-EmbeddedWorkArea::EmbeddedWorkArea(QWidget * w): GuiWorkArea(w),
- delayed_focus_timer_(this)
+EmbeddedWorkArea::EmbeddedWorkArea(QWidget * w): GuiWorkArea(w)
{
buffer_ = theBufferList().newBuffer(
support::FileName::tempName().absFilename() + "_embedded.internal");
- LASSERT(buffer_ != 0, /* */);
-
buffer_->setUnnamed(true);
buffer_->setFullyLoaded(true);
setBuffer(*buffer_);
- setUpdatesEnabled(false);
setDialogMode(true);
}
}
-void EmbeddedWorkArea::onDelayedFocus()
-{
- LYXERR(Debug::DEBUG, "Delayed Focus");
- view().setCurrentWorkArea(this);
- setFocus();
-}
-
-
-void EmbeddedWorkArea::showEvent(QShowEvent *ev)
+void EmbeddedWorkArea::closeEvent(QCloseEvent * ev)
{
- view().setCurrentWorkArea(this);
- redraw();
- setFocus();
- installEventFilter(this);
- connect(&delayed_focus_timer_, SIGNAL(timeout()), this,
- SLOT(onDelayedFocus()));
- delayed_focus_timer_.setSingleShot(true);
- delayed_focus_timer_.start(100);
-
- GuiWorkArea::showEvent(ev);
+ disable();
+ GuiWorkArea::closeEvent(ev);
}
-void EmbeddedWorkArea::closeEvent(QCloseEvent * close_event)
+void EmbeddedWorkArea::hideEvent(QHideEvent * ev)
{
- LYXERR(Debug::DEBUG, "FindAndReplace::closeEvent()");
- removeEventFilter(this);
disable();
-
- GuiWorkArea::closeEvent(close_event);
+ GuiWorkArea::hideEvent(ev);
}
void EmbeddedWorkArea::disable()
{
- // Ok, closing the window before 100ms may be impossible, however...
- delayed_focus_timer_.stop();
- if (view().currentWorkArea() == this) {
- LASSERT(view().currentMainWorkArea(), /* */);
- view().setCurrentWorkArea(view().currentMainWorkArea());
- }
stopBlinkingCursor();
+ if (view().currentWorkArea() != this)
+ return;
+ // No problem if currentMainWorkArea() is 0 (setCurrentWorkArea()
+ // tolerates it and shows the background logo), what happens if
+ // an EmbeddedWorkArea is closed after closing all document WAs
+ view().setCurrentWorkArea(view().currentMainWorkArea());
}
////////////////////////////////////////////////////////////////////
#ifdef Q_WS_MACX
setStyle(&noTabFrameMacStyle);
#endif
+#if QT_VERSION < 0x040500
+ lyxrc.single_close_tab_button = true;
+#endif
QPalette pal = palette();
pal.setColor(QPalette::Active, QPalette::Button,
QObject::connect(this, SIGNAL(currentChanged(int)),
this, SLOT(on_currentTabChanged(int)));
- QToolButton * closeBufferButton = new QToolButton(this);
+ closeBufferButton = new QToolButton(this);
closeBufferButton->setPalette(pal);
// FIXME: rename the icon to closebuffer.png
- closeBufferButton->setIcon(QIcon(":/images/closetab.png"));
+ closeBufferButton->setIcon(QIcon(getPixmap("images/", "closetab", "png")));
closeBufferButton->setText("Close File");
closeBufferButton->setAutoRaise(true);
closeBufferButton->setCursor(Qt::ArrowCursor);
tb->setContextMenuPolicy(Qt::CustomContextMenu);
connect(tb, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(showContextMenu(const QPoint &)));
+#if QT_VERSION >= 0x040500
+ connect(tb, SIGNAL(tabCloseRequested(int)),
+ this, SLOT(closeTab(int)));
+#endif
setUsesScrollButtons(true);
}
}
if (lyxrc.full_screen_tabbar)
- showBar(!full_screen && count()>1);
+ showBar(!full_screen && count() > 1);
}
{
tabBar()->setEnabled(show);
tabBar()->setVisible(show);
+ closeBufferButton->setVisible(show && lyxrc.single_close_tab_button);
+#if QT_VERSION >= 0x040500
+ setTabsClosable(!lyxrc.single_close_tab_button);
+#endif
}
if (currentWorkArea() && currentWorkArea()->isFullScreen())
setFullScreen(true);
else
- // Hide tabbar if there's only one tab.
+ // Show tabbar only if there's more than one tab.
showBar(count() > 1);
- } else {
+ } else
lastWorkAreaRemoved();
- }
updateTabTexts();
return;
GuiWorkArea * wa = dynamic_cast<GuiWorkArea *>(widget(i));
LASSERT(wa, return);
- BufferView & bv = wa->bufferView();
- bv.cursor().fixIfBroken();
- bv.updateMetrics();
wa->setUpdatesEnabled(true);
- wa->redraw();
+ wa->redraw(true);
wa->setFocus();
///
currentWorkAreaChanged(wa);
LYXERR(Debug::GUI, "currentTabChanged " << i
- << "File" << bv.buffer().absFileName());
+ << " File: " << wa->bufferView().buffer().absFileName());
}
void TabWorkArea::closeCurrentBuffer()
{
- if (clicked_tab_ != -1)
- setCurrentIndex(clicked_tab_);
-
- lyx::dispatch(FuncRequest(LFUN_BUFFER_CLOSE));
+ GuiWorkArea * wa;
+ if (clicked_tab_ == -1)
+ wa = currentWorkArea();
+ else {
+ wa = dynamic_cast<GuiWorkArea *>(widget(clicked_tab_));
+ LASSERT(wa, /**/);
+ }
+ wa->view().closeWorkArea(wa);
}
-void TabWorkArea::closeCurrentTab()
+void TabWorkArea::hideCurrentTab()
{
+ GuiWorkArea * wa;
if (clicked_tab_ == -1)
- removeWorkArea(currentWorkArea());
+ wa = currentWorkArea();
else {
- GuiWorkArea * wa = dynamic_cast<GuiWorkArea *>(widget(clicked_tab_));
+ wa = dynamic_cast<GuiWorkArea *>(widget(clicked_tab_));
LASSERT(wa, /**/);
- removeWorkArea(wa);
}
+ wa->view().hideWorkArea(wa);
}
+
+void TabWorkArea::closeTab(int index)
+{
+ on_currentTabChanged(index);
+ GuiWorkArea * wa;
+ if (index == -1)
+ wa = currentWorkArea();
+ else {
+ wa = dynamic_cast<GuiWorkArea *>(widget(index));
+ LASSERT(wa, /**/);
+ }
+ wa->view().closeWorkArea(wa);
+}
+
+
///
class DisplayPath {
public:
DisplayPath(int tab, FileName const & filename)
: tab_(tab)
{
- filename_ = toqstr(filename.onlyFileNameWithoutExt());
+ filename_ = (filename.extension() == "lyx") ?
+ toqstr(filename.onlyFileNameWithoutExt())
+ : toqstr(filename.onlyFileName());
postfix_ = toqstr(filename.absoluteFilePath()).
split("/", QString::SkipEmptyParts);
postfix_.pop_back();
// show tab popup
QMenu popup;
- popup.addAction(QIcon(":/images/hidetab.png"),
- qt_("Hide tab"), this, SLOT(closeCurrentTab()));
- popup.addAction(QIcon(":/images/closetab.png"),
+ popup.addAction(QIcon(getPixmap("images/", "hidetab", "png")),
+ qt_("Hide tab"), this, SLOT(hideCurrentTab()));
+ popup.addAction(QIcon(getPixmap("images/", "closetab", "png")),
qt_("Close tab"), this, SLOT(closeCurrentBuffer()));
popup.exec(tabBar()->mapToGlobal(pos));
: QTabBar(parent)
{
setAcceptDrops(true);
+#if QT_VERSION >= 0x040500
+ setTabsClosable(!lyxrc.single_close_tab_button);
+#endif
}