make WorkArea a pure interface, move all implementation to GuiWorkArea

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@21557 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
André Pönitz 2007-11-12 22:15:51 +00:00
parent 963470c60e
commit 34859c9a4f
10 changed files with 448 additions and 507 deletions

View File

@ -1,6 +1,6 @@
// -*- C++ -*-
/**
* \file key_state.h
* \file KeyModifier.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
@ -19,10 +19,10 @@ namespace lyx {
/// modifier key states
enum KeyModifier {
NoModifier = 0, //< no modifiers held
NoModifier = 0, //< no modifiers held
ControlModifier = 1, //< control button held
AltModifier = 2, //< alt/meta key held
ShiftModifier = 4 //< shift key held
AltModifier = 2, //< alt/meta key held
ShiftModifier = 4 //< shift key held
};
@ -42,4 +42,4 @@ inline void operator|=(KeyModifier & s1, KeyModifier s2)
} // namespace lyx
#endif // KEY_STATE_H
#endif // KEYMODIFIER_H

View File

@ -34,7 +34,6 @@ liblyxfrontends_la_SOURCES = \
Clipboard.h \
Gui.h \
Selection.h \
WorkArea.cpp \
WorkArea.h \
WorkAreaManager.cpp \
WorkAreaManager.h \

View File

@ -1,349 +0,0 @@
/**
* \file WorkArea.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Abdelrazak Younes
*
* Full author contact details are available in file CREDITS.
*
* Splash screen code added by Angus Leeming
*/
#include <config.h>
#include "frontends/WorkArea.h"
#include "frontends/Application.h"
#include "frontends/Dialogs.h"
#include "frontends/FontMetrics.h"
#include "frontends/LyXView.h"
#include "frontends/WorkAreaManager.h"
#include "BufferView.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "CoordCache.h"
#include "Cursor.h"
#include "debug.h"
#include "Font.h"
#include "FuncRequest.h"
#include "KeySymbol.h"
#include "Language.h"
#include "LyXFunc.h"
#include "LyXRC.h"
#include "MetricsInfo.h"
#include "gettext.h"
#include "support/FileName.h"
#include "support/filetools.h"
#include "support/ForkedcallsController.h"
#include <boost/noncopyable.hpp>
#include <boost/bind.hpp>
#include <boost/current_function.hpp>
using std::endl;
using std::min;
using std::max;
using std::string;
namespace {
// All the below connection objects are needed because of a bug in some
// versions of GCC (<=2.96 are on the suspects list.) By having and assigning
// to these connections we avoid a segfault upon startup, and also at exit.
// (Lgb)
boost::signals::connection timecon;
} // anon namespace
namespace lyx {
using support::ForkedcallsController;
using support::makeDisplayPath;
using support::onlyFilename;
namespace frontend {
WorkArea::WorkArea(Buffer & buffer, LyXView & lv)
: buffer_view_(new BufferView(buffer)), lyx_view_(&lv),
cursor_visible_(false), cursor_timeout_(400)
{
buffer.workAreaManager().add(this);
// Setup the signals
timecon = cursor_timeout_.timeout
.connect(boost::bind(&WorkArea::toggleCursor, this));
cursor_timeout_.start();
}
WorkArea::~WorkArea()
{
buffer_view_->buffer().workAreaManager().remove(this);
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_;
}
BufferView const & WorkArea::bufferView() const
{
return *buffer_view_;
}
void WorkArea::stopBlinkingCursor()
{
cursor_timeout_.stop();
hideCursor();
}
void WorkArea::startBlinkingCursor()
{
showCursor();
cursor_timeout_.restart();
}
void WorkArea::redraw()
{
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()) {
// FIXME: it would be nice to optimize for the off-screen case.
buffer_view_->updateMetrics();
buffer_view_->cursor().fixIfBroken();
}
updateScrollbar();
// update cursor position, because otherwise it has to wait until
// the blinking interval is over
if (cursor_visible_) {
hideCursor();
showCursor();
}
ViewMetricsInfo const & vi = buffer_view_->viewMetricsInfo();
LYXERR(Debug::WORKAREA) << "WorkArea::redraw screen" << endl;
int const ymin = std::max(vi.y1, 0);
int const ymax = vi.p2 < vi.size - 1 ? vi.y2 : height();
expose(0, ymin, width(), ymax - ymin);
//LYXERR(Debug::WORKAREA)
//<< " ymin = " << ymin << " width() = " << width()
// << " ymax-ymin = " << ymax-ymin << std::endl;
if (lyxerr.debugging(Debug::WORKAREA))
buffer_view_->coordCache().dump();
}
void WorkArea::processKeySym(KeySymbol const & key, KeyModifier mod)
{
// In order to avoid bad surprise in the middle of an operation, we better stop
// the blinking cursor.
stopBlinkingCursor();
theLyXFunc().setLyXView(lyx_view_);
theLyXFunc().processKeySym(key, mod);
}
void WorkArea::dispatch(FuncRequest const & cmd0, KeyModifier mod)
{
// Handle drag&drop
if (cmd0.action == LFUN_FILE_OPEN) {
lyx_view_->dispatch(cmd0);
return;
}
theLyXFunc().setLyXView(lyx_view_);
FuncRequest cmd;
if (cmd0.action == LFUN_MOUSE_PRESS) {
if (mod == ShiftModifier)
cmd = FuncRequest(cmd0, "region-select");
else if (mod == ControlModifier)
cmd = FuncRequest(cmd0, "paragraph-select");
else
cmd = cmd0;
}
else
cmd = cmd0;
// In order to avoid bad surprise in the middle of an operation, we better stop
// the blinking cursor.
if (!(cmd.action == LFUN_MOUSE_MOTION
&& cmd.button() == mouse_button::none))
stopBlinkingCursor();
buffer_view_->mouseEventDispatch(cmd);
// Skip these when selecting
if (cmd.action != LFUN_MOUSE_MOTION) {
lyx_view_->updateLayoutChoice(false);
lyx_view_->updateToolbars();
}
// GUI tweaks except with mouse motion with no button pressed.
if (!(cmd.action == LFUN_MOUSE_MOTION
&& cmd.button() == mouse_button::none)) {
// 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();
// Show the cursor immediately after any operation.
startBlinkingCursor();
}
}
void WorkArea::resizeBufferView()
{
// WARNING: Please don't put any code that will trigger a repaint here!
// We are already inside a paint event.
lyx_view_->setBusy(true);
buffer_view_->resize(width(), height());
lyx_view_->updateLayoutChoice(false);
lyx_view_->setBusy(false);
}
void WorkArea::updateScrollbar()
{
buffer_view_->updateScrollbar();
ScrollbarParameters const & scroll_ = buffer_view_->scrollbarParameters();
setScrollbarParams(scroll_.height, scroll_.position,
scroll_.lineScrollHeight);
}
void WorkArea::showCursor()
{
if (cursor_visible_)
return;
CursorShape shape = BAR_SHAPE;
Font const & realfont = buffer_view_->cursor().real_current_font;
BufferParams const & bp = buffer_view_->buffer().params();
bool const samelang = realfont.language() == bp.language;
bool const isrtl = realfont.isVisibleRightToLeft();
if (!samelang || isrtl != bp.language->rightToLeft()) {
shape = L_SHAPE;
if (isrtl)
shape = REVERSED_L_SHAPE;
}
// The ERT language hack needs fixing up
if (realfont.language() == latex_language)
shape = BAR_SHAPE;
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;
buffer_view_->cursor().getPos(x, y);
y -= asc;
// if it doesn't touch the screen, don't try to show it
if (y + h < 0 || y >= height())
return;
cursor_visible_ = true;
showCursor(x, y, h, shape);
}
void WorkArea::hideCursor()
{
if (!cursor_visible_)
return;
cursor_visible_ = false;
removeCursor();
}
void WorkArea::toggleCursor()
{
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();
cursor_timeout_.restart();
}
void WorkArea::updateWindowTitle()
{
docstring maximize_title;
docstring minimize_title;
Buffer & buf = buffer_view_->buffer();
string const cur_title = buf.absFileName();
if (!cur_title.empty()) {
maximize_title = makeDisplayPath(cur_title, 30);
minimize_title = from_utf8(onlyFilename(cur_title));
if (!buf.isClean()) {
maximize_title += _(" (changed)");
minimize_title += char_type('*');
}
if (buf.isReadonly())
maximize_title += _(" (read only)");
}
setWindowTitle(maximize_title, minimize_title);
}
void WorkArea::setReadOnly(bool)
{
updateWindowTitle();
if (this == lyx_view_->currentWorkArea())
lyx_view_->getDialogs().updateBufferDependent(false);
}
} // namespace frontend
} // namespace lyx

View File

@ -15,18 +15,10 @@
#define BASE_WORKAREA_H
#include "frontends/KeyModifier.h"
#include "frontends/Delegates.h"
#include "support/Timeout.h"
#include "support/docstring.h"
#undef CursorShape
namespace lyx {
class Buffer;
class BufferView;
class FuncRequest;
class KeySymbol;
namespace frontend {
@ -34,16 +26,6 @@ namespace frontend {
class LyXView;
class Painter;
/// types of cursor in work area
enum CursorShape {
/// normal I-beam
BAR_SHAPE,
/// L-shape for locked insets of a different language
L_SHAPE,
/// reverse L-shape for RTL text
REVERSED_L_SHAPE
};
/**
* The work area class represents the widget that provides the
* view onto a document. It is owned by the BufferView, and
@ -55,22 +37,22 @@ class WorkArea
{
public:
///
WorkArea(Buffer & buffer, LyXView & lv);
WorkArea() {}
virtual ~WorkArea();
///
void setLyXView(LyXView & lv) { lyx_view_ = &lv; }
virtual void setLyXView(LyXView & lv) = 0;
///
BufferView & bufferView();
virtual BufferView & bufferView() = 0;
///
BufferView const & bufferView() const;
virtual BufferView const & bufferView() const = 0;
/// \return true if has the keyboard input focus.
/// return true if has the keyboard input focus.
virtual bool hasFocus() const = 0;
/// \return true if has this WorkArea is visible.
/// return true if has this WorkArea is visible.
virtual bool isVisible() const = 0;
/// return the width of the work area in pixels
@ -91,65 +73,23 @@ public:
virtual void scheduleRedraw() = 0;
/// redraw the screen, without using existing pixmap
virtual void redraw();
virtual void redraw() = 0;
///
void stopBlinkingCursor();
void startBlinkingCursor();
virtual void stopBlinkingCursor() = 0;
virtual void startBlinkingCursor() = 0;
/// Process Key pressed event.
/// This needs to be public because it is accessed externally by GuiView.
void processKeySym(KeySymbol const & key, KeyModifier mod);
virtual void processKeySym(KeySymbol const & key, KeyModifier mod) = 0;
/// close this work area.
/// Slot for Buffer::closing signal.
void close();
virtual void close() = 0;
/// This function is called when the buffer readonly status change.
virtual void setReadOnly(bool);
virtual void setReadOnly(bool) = 0;
/// Update window titles of all users.
virtual void updateWindowTitle();
protected:
/// cause the display of the given area of the work area
virtual void expose(int x, int y, int w, int h) = 0;
/// set title of window.
/**
* @param t main window title
* @param it iconified (short) title
*/
virtual void setWindowTitle(docstring const & t, docstring const & it) = 0;
///
void dispatch(FuncRequest const & cmd0, KeyModifier = NoModifier);
///
void resizeBufferView();
/// hide the visible cursor, if it is visible
void hideCursor();
/// show the cursor if it is not visible
void showCursor();
/// toggle the cursor's visibility
void toggleCursor();
/// hide the cursor
virtual void removeCursor() = 0;
/// paint the cursor and store the background
virtual void showCursor(int x, int y, int h, CursorShape shape) = 0;
///
void updateScrollbar();
///
BufferView * buffer_view_;
///
LyXView * lyx_view_;
private:
/// is the cursor currently displayed
bool cursor_visible_;
///
Timeout cursor_timeout_;
virtual void updateWindowTitle() = 0;
};
} // namespace frontend

View File

@ -11,16 +11,12 @@
#include <config.h>
#include "WorkArea.h"
#include "WorkAreaManager.h"
using std::list;
#include "WorkArea.h"
namespace lyx {
extern bool quitting;
namespace frontend {
void WorkAreaManager::add(WorkArea * wa)
@ -37,11 +33,8 @@ void WorkAreaManager::remove(WorkArea * wa)
void WorkAreaManager::redrawAll()
{
for (list<WorkArea *>::iterator it = work_areas_.begin();
it != work_areas_.end(); ) {
for (iterator it = work_areas_.begin(); it != work_areas_.end(); ++it)
(*it)->redraw();
++it;
}
}
@ -55,21 +48,15 @@ void WorkAreaManager::closeAll()
void WorkAreaManager::setReadOnly(bool on)
{
for (list<WorkArea *>::iterator it = work_areas_.begin();
it != work_areas_.end(); ) {
for (iterator it = work_areas_.begin(); it != work_areas_.end(); ++it)
(*it)->setReadOnly(on);
++it;
}
}
void WorkAreaManager::updateTitles()
{
for (list<WorkArea *>::iterator it = work_areas_.begin();
it != work_areas_.end(); ) {
for (iterator it = work_areas_.begin(); it != work_areas_.end(); ++it)
(*it)->updateWindowTitle();
++it;
}
}
} // namespace frontend

View File

@ -28,27 +28,24 @@ class WorkArea;
class WorkAreaManager
{
public:
///
WorkAreaManager() {}
///
void add(WorkArea * wa);
///
void remove(WorkArea * wa);
///
void redrawAll();
///
void closeAll();
/// This function is called when the buffer readonly status change.
virtual void setReadOnly(bool);
void setReadOnly(bool);
/// Update window titles of all users.
virtual void updateTitles();
void updateTitles();
private:
typedef std::list<WorkArea *>::iterator iterator;
///
std::list<WorkArea *> work_areas_;
};

View File

@ -121,7 +121,7 @@ private:
QPixmap * splash_;
};
};
} // namespace anon
struct GuiView::GuiViewPrivate

View File

@ -140,14 +140,20 @@ private:
/// in order to catch Tab key press.
bool event(QEvent * e);
bool focusNextPrevChild(bool);
///
QRect updateFloatingGeometry();
private:
///
struct GuiViewPrivate;
GuiViewPrivate & d;
///
QTimer statusbar_timer_;
/// are we quitting by the menu?
bool quitting_by_menu_;
///
QRect updateFloatingGeometry();
///
QRect floatingGeometry_;
@ -161,9 +167,6 @@ private:
};
ToolbarSize toolbarSize_;
struct GuiViewPrivate;
GuiViewPrivate& d;
};

View File

@ -13,25 +13,38 @@
#include "GuiWorkArea.h"
#include "GuiApplication.h"
#include "GuiPainter.h"
#include "GuiKeySymbol.h"
#include "qt_helpers.h"
#include "frontends/LyXView.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "BufferView.h"
#include "CoordCache.h"
#include "Cursor.h"
#include "debug.h"
#include "Font.h"
#include "FuncRequest.h"
#include "gettext.h"
#include "GuiApplication.h"
#include "GuiKeySymbol.h"
#include "GuiPainter.h"
#include "KeySymbol.h"
#include "Language.h"
#include "LyXFunc.h"
#include "LyXRC.h"
#include "MetricsInfo.h"
#include "qt_helpers.h"
#include "version.h"
#include "graphics/GraphicsImage.h"
#include "graphics/GraphicsLoader.h"
#include "support/FileName.h"
#include "support/ForkedcallsController.h"
#include "frontends/Application.h"
#include "frontends/Dialogs.h" // only used in setReadOnly
#include "frontends/FontMetrics.h"
#include "frontends/LyXView.h"
#include "frontends/WorkAreaManager.h"
#include <QInputContext>
#include <QLayout>
#include <QMainWindow>
@ -42,8 +55,8 @@
#include <QTabBar>
#include <QTimer>
#include <boost/current_function.hpp>
#include <boost/bind.hpp>
#include <boost/current_function.hpp>
#ifdef Q_WS_X11
#include <QX11Info>
@ -60,11 +73,15 @@ int const CursorWidth = 1;
#undef NoModifier
using std::endl;
using std::min;
using std::max;
using std::string;
namespace lyx {
using support::FileName;
using support::ForkedcallsController;
/// return the LyX mouse button state from Qt's
static mouse_button::state q_button_state(Qt::MouseButton button)
@ -174,10 +191,31 @@ SyntheticMouseEvent::SyntheticMouseEvent()
{}
GuiWorkArea::GuiWorkArea(Buffer & buf, LyXView & lv)
: WorkArea(buf, lv), need_resize_(false), schedule_redraw_(false),
preedit_lines_(1)
// All the below connection objects are needed because of a bug in some
// versions of GCC (<=2.96 are on the suspects list.) By having and assigning
// to these connections we avoid a segfault upon startup, and also at exit.
// (Lgb)
static boost::signals::connection timecon;
// HACK: FIXME
WorkArea::~WorkArea() {}
GuiWorkArea::GuiWorkArea(Buffer & buffer, LyXView & lv)
: buffer_view_(new BufferView(buffer)), lyx_view_(&lv),
cursor_visible_(false), cursor_timeout_(400),
need_resize_(false), schedule_redraw_(false),
preedit_lines_(1)
{
buffer.workAreaManager().add(this);
// Setup the signals
timecon = cursor_timeout_.timeout
.connect(boost::bind(&GuiWorkArea::toggleCursor, this));
cursor_timeout_.start();
screen_ = QPixmap(viewport()->width(), viewport()->height());
cursor_ = new frontend::CursorWidget();
cursor_->hide();
@ -200,7 +238,7 @@ GuiWorkArea::GuiWorkArea(Buffer & buf, LyXView & lv)
synthetic_mouse_event_.timeout.timeout.connect(
boost::bind(&GuiWorkArea::generateSyntheticMouseEvent,
this));
this));
// Initialize the vertical Scroll Bar
QObject::connect(verticalScrollBar(), SIGNAL(actionTriggered(int)),
@ -225,6 +263,237 @@ GuiWorkArea::GuiWorkArea(Buffer & buf, LyXView & lv)
}
GuiWorkArea::~GuiWorkArea()
{
buffer_view_->buffer().workAreaManager().remove(this);
delete buffer_view_;
}
void GuiWorkArea::close()
{
lyx_view_->removeWorkArea(this);
}
BufferView & GuiWorkArea::bufferView()
{
return *buffer_view_;
}
BufferView const & GuiWorkArea::bufferView() const
{
return *buffer_view_;
}
void GuiWorkArea::stopBlinkingCursor()
{
cursor_timeout_.stop();
hideCursor();
}
void GuiWorkArea::startBlinkingCursor()
{
showCursor();
cursor_timeout_.restart();
}
void GuiWorkArea::redraw()
{
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()) {
// FIXME: it would be nice to optimize for the off-screen case.
buffer_view_->updateMetrics();
buffer_view_->cursor().fixIfBroken();
}
updateScrollbar();
// update cursor position, because otherwise it has to wait until
// the blinking interval is over
if (cursor_visible_) {
hideCursor();
showCursor();
}
ViewMetricsInfo const & vi = buffer_view_->viewMetricsInfo();
LYXERR(Debug::WORKAREA) << "WorkArea::redraw screen" << endl;
int const ymin = std::max(vi.y1, 0);
int const ymax = vi.p2 < vi.size - 1 ? vi.y2 : height();
expose(0, ymin, width(), ymax - ymin);
//LYXERR(Debug::WORKAREA)
//<< " ymin = " << ymin << " width() = " << width()
// << " ymax-ymin = " << ymax-ymin << std::endl;
if (lyxerr.debugging(Debug::WORKAREA))
buffer_view_->coordCache().dump();
}
void GuiWorkArea::processKeySym(KeySymbol const & key, KeyModifier mod)
{
// In order to avoid bad surprise in the middle of an operation,
// we better stop the blinking cursor.
stopBlinkingCursor();
theLyXFunc().setLyXView(lyx_view_);
theLyXFunc().processKeySym(key, mod);
}
void GuiWorkArea::dispatch(FuncRequest const & cmd0, KeyModifier mod)
{
// Handle drag&drop
if (cmd0.action == LFUN_FILE_OPEN) {
lyx_view_->dispatch(cmd0);
return;
}
theLyXFunc().setLyXView(lyx_view_);
FuncRequest cmd;
if (cmd0.action == LFUN_MOUSE_PRESS) {
if (mod == ShiftModifier)
cmd = FuncRequest(cmd0, "region-select");
else if (mod == ControlModifier)
cmd = FuncRequest(cmd0, "paragraph-select");
else
cmd = cmd0;
}
else
cmd = cmd0;
// In order to avoid bad surprise in the middle of an operation, we better stop
// the blinking cursor.
if (!(cmd.action == LFUN_MOUSE_MOTION
&& cmd.button() == mouse_button::none))
stopBlinkingCursor();
buffer_view_->mouseEventDispatch(cmd);
// Skip these when selecting
if (cmd.action != LFUN_MOUSE_MOTION) {
lyx_view_->updateLayoutChoice(false);
lyx_view_->updateToolbars();
}
// GUI tweaks except with mouse motion with no button pressed.
if (!(cmd.action == LFUN_MOUSE_MOTION
&& cmd.button() == mouse_button::none)) {
// 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();
// Show the cursor immediately after any operation.
startBlinkingCursor();
}
}
void GuiWorkArea::resizeBufferView()
{
// WARNING: Please don't put any code that will trigger a repaint here!
// We are already inside a paint event.
lyx_view_->setBusy(true);
buffer_view_->resize(width(), height());
lyx_view_->updateLayoutChoice(false);
lyx_view_->setBusy(false);
}
void GuiWorkArea::updateScrollbar()
{
buffer_view_->updateScrollbar();
ScrollbarParameters const & scroll_ = buffer_view_->scrollbarParameters();
setScrollbarParams(scroll_.height, scroll_.position,
scroll_.lineScrollHeight);
}
void GuiWorkArea::showCursor()
{
if (cursor_visible_)
return;
CursorShape shape = BAR_SHAPE;
Font const & realfont = buffer_view_->cursor().real_current_font;
BufferParams const & bp = buffer_view_->buffer().params();
bool const samelang = realfont.language() == bp.language;
bool const isrtl = realfont.isVisibleRightToLeft();
if (!samelang || isrtl != bp.language->rightToLeft()) {
shape = L_SHAPE;
if (isrtl)
shape = REVERSED_L_SHAPE;
}
// The ERT language hack needs fixing up
if (realfont.language() == latex_language)
shape = BAR_SHAPE;
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;
buffer_view_->cursor().getPos(x, y);
y -= asc;
// if it doesn't touch the screen, don't try to show it
if (y + h < 0 || y >= height())
return;
cursor_visible_ = true;
showCursor(x, y, h, shape);
}
void GuiWorkArea::hideCursor()
{
if (!cursor_visible_)
return;
cursor_visible_ = false;
removeCursor();
}
void GuiWorkArea::toggleCursor()
{
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();
cursor_timeout_.restart();
}
void GuiWorkArea::setScrollbarParams(int h, int scroll_pos, int scroll_line_step)
{
if (verticalScrollBarPolicy() != Qt::ScrollBarAlwaysOn)
@ -441,7 +710,7 @@ void GuiWorkArea::doubleClickTimeout()
void GuiWorkArea::mouseDoubleClickEvent(QMouseEvent * ev)
{
dc_event_ = double_click(ev);
dc_event_ = DoubleClick(ev);
QTimer::singleShot(QApplication::doubleClickInterval(), this,
SLOT(doubleClickTimeout()));
FuncRequest cmd(LFUN_MOUSE_DOUBLE,
@ -479,8 +748,8 @@ void GuiWorkArea::paintEvent(QPaintEvent * ev)
screen_ = QPixmap(viewport()->width(), viewport()->height());
resizeBufferView();
updateScreen();
WorkArea::hideCursor();
WorkArea::showCursor();
hideCursor();
showCursor();
need_resize_ = false;
}
@ -704,18 +973,51 @@ QVariant GuiWorkArea::inputMethodQuery(Qt::InputMethodQuery query) const
}
void GuiWorkArea::updateWindowTitle()
{
docstring maximize_title;
docstring minimize_title;
Buffer & buf = buffer_view_->buffer();
FileName const fileName = buf.fileName();
if (!fileName.empty()) {
maximize_title = fileName.displayName(30);
minimize_title = from_utf8(fileName.onlyFileName());
if (!buf.isClean()) {
maximize_title += _(" (changed)");
minimize_title += char_type('*');
}
if (buf.isReadonly())
maximize_title += _(" (read only)");
}
setWindowTitle(maximize_title, minimize_title);
}
void GuiWorkArea::setReadOnly(bool)
{
updateWindowTitle();
if (this == lyx_view_->currentWorkArea())
lyx_view_->getDialogs().updateBufferDependent(false);
}
////////////////////////////////////////////////////////////////////
//
// TabWorkArea
//
////////////////////////////////////////////////////////////////////
TabWorkArea::TabWorkArea(QWidget * parent): QTabWidget(parent)
TabWorkArea::TabWorkArea(QWidget * parent) : QTabWidget(parent)
{
QPalette pal = palette();
pal.setColor(QPalette::Active, QPalette::Button, pal.color(QPalette::Active, QPalette::Window));
pal.setColor(QPalette::Disabled, QPalette::Button, pal.color(QPalette::Disabled, QPalette::Window));
pal.setColor(QPalette::Inactive, QPalette::Button, pal.color(QPalette::Inactive, QPalette::Window));
pal.setColor(QPalette::Active, QPalette::Button,
pal.color(QPalette::Active, QPalette::Window));
pal.setColor(QPalette::Disabled, QPalette::Button,
pal.color(QPalette::Disabled, QPalette::Window));
pal.setColor(QPalette::Inactive, QPalette::Button,
pal.color(QPalette::Inactive, QPalette::Window));
QToolButton * closeTabButton = new QToolButton(this);
closeTabButton->setPalette(pal);

View File

@ -39,23 +39,38 @@ class QPaintEvent;
#endif
namespace lyx {
class Buffer;
namespace frontend {
class LyXView;
/// types of cursor in work area
enum CursorShape {
/// normal I-beam
BAR_SHAPE,
/// L-shape for locked insets of a different language
L_SHAPE,
/// reverse L-shape for RTL text
REVERSED_L_SHAPE
};
/// for emulating triple click
class double_click {
class DoubleClick {
public:
///
DoubleClick() : state(Qt::NoButton), active(false) {}
///
DoubleClick(QMouseEvent * e) : state(e->button()), active(true) {}
///
bool operator==(QMouseEvent const & e) { return state == e.button(); }
///
public:
///
Qt::MouseButton state;
///
bool active;
bool operator==(QMouseEvent const & e) {
return state == e.button();
}
double_click()
: state(Qt::NoButton), active(false) {}
double_click(QMouseEvent * e)
: state(e->button()), active(true) {}
};
/** Qt only emits mouse events when the mouse is being moved, but
@ -79,11 +94,12 @@ public:
double scrollbar_value_old;
};
/**
* Qt-specific implementation of the work area
* (buffer view GUI)
* Implementation of the work area (buffer view GUI)
*/
class CursorWidget;
class CursorWidget;
class GuiWorkArea : public QAbstractScrollArea, public WorkArea
{
Q_OBJECT
@ -91,6 +107,8 @@ class GuiWorkArea : public QAbstractScrollArea, public WorkArea
public:
///
GuiWorkArea(Buffer & buffer, LyXView & lv);
///
~GuiWorkArea();
///
bool hasFocus() const { return QAbstractScrollArea::hasFocus(); }
@ -116,7 +134,36 @@ public:
/// hide the cursor
virtual void removeCursor();
///
void setLyXView(LyXView & lv) { lyx_view_ = &lv; }
///
BufferView & bufferView();
///
BufferView const & bufferView() const;
///
void redraw();
///
void stopBlinkingCursor();
///
void startBlinkingCursor();
///
void processKeySym(KeySymbol const & key, KeyModifier mod);
public Q_SLOTS:
/// Adjust the LyX buffer view with the position of the scrollbar.
/**
* The action argument is not used in the the code, it is there
* only for the connection to the vertical srollbar signal which
* emits an 'int' action.
*/
void adjustViewWithScrollBar(int action = 0);
/// timer to limit triple clicks
void doubleClickTimeout();
/// close this work area.
/// Slot for Buffer::closing signal.
void close();
////
void setWindowTitle(docstring const & t, docstring const & it);
Q_SIGNALS:
@ -124,6 +171,11 @@ Q_SIGNALS:
void titleChanged(GuiWorkArea *);
private:
/// This function is called when the buffer readonly status change.
void setReadOnly(bool);
/// Update window titles of all users.
void updateWindowTitle();
///
void focusInEvent(QFocusEvent *);
///
@ -149,25 +201,34 @@ private:
/// IM query
QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
public Q_SLOTS:
/// Adjust the LyX buffer view with the position of the scrollbar.
/**
* The action argument is not used in the the code, it is there
* only for the connection to the vertical srollbar signal which
* emits an 'int' action.
*/
void adjustViewWithScrollBar(int action = 0);
/// timer to limit triple clicks
void doubleClickTimeout();
private:
/// The slot connected to SyntheticMouseEvent::timeout.
void generateSyntheticMouseEvent();
///
void dispatch(FuncRequest const & cmd0, KeyModifier = NoModifier);
///
void resizeBufferView();
/// hide the visible cursor, if it is visible
void hideCursor();
/// show the cursor if it is not visible
void showCursor();
/// toggle the cursor's visibility
void toggleCursor();
///
void updateScrollbar();
///
BufferView * buffer_view_;
///
LyXView * lyx_view_;
/// is the cursor currently displayed
bool cursor_visible_;
///
Timeout cursor_timeout_;
///
SyntheticMouseEvent synthetic_mouse_event_;
///
double_click dc_event_;
DoubleClick dc_event_;
///
CursorWidget * cursor_;
@ -181,7 +242,8 @@ private:
bool schedule_redraw_;
///
int preedit_lines_;
}; //GuiWorkArea
}; // GuiWorkArea
/// A tabbed set of GuiWorkAreas.
class TabWorkArea : public QTabWidget