New class InsetCaptionable

This generalises the new use of TocBuilder (97e8101) to listings and wraps and
removes some duplicate code.

Make sure that we will never write an empty float type again in the future
(#9760)
This commit is contained in:
Guillaume Munch 2015-09-02 19:53:13 +01:00
parent 94e992c5ed
commit 9b7ccbfc80
14 changed files with 234 additions and 152 deletions

View File

@ -573,6 +573,7 @@ SOURCEFILESINSETS = \
insets/InsetBox.cpp \
insets/InsetBranch.cpp \
insets/InsetCaption.cpp \
insets/InsetCaptionable.cpp \
insets/InsetCitation.cpp \
insets/InsetCollapsable.cpp \
insets/InsetCommand.cpp \
@ -631,6 +632,7 @@ HEADERFILESINSETS = \
insets/InsetBox.h \
insets/InsetBranch.h \
insets/InsetCaption.h \
insets/InsetCaptionable.h \
insets/InsetCitation.h \
insets/InsetCode.h \
insets/InsetCollapsable.h \

View File

@ -80,8 +80,9 @@ public:
TocModel::TocModel(QObject * parent)
: model_(new TocTypeModel(parent)),
sorted_model_(new QSortFilterProxyModel(parent)),
is_sorted_(false), toc_(0), maxdepth_(0), mindepth_(0)
sorted_model_(new QSortFilterProxyModel(parent)),
is_sorted_(false), toc_(make_shared<Toc const>()),
maxdepth_(0), mindepth_(0)
{
sorted_model_->setSortLocaleAware(true);
sorted_model_->setSourceModel(model_);
@ -108,6 +109,7 @@ void TocModel::clear()
{
model_->blockSignals(true);
model_->clear();
toc_ = make_shared<Toc const>();
model_->blockSignals(false);
}
@ -157,9 +159,9 @@ void TocModel::updateItem(DocIterator const & dit)
}
void TocModel::reset(Toc const & toc)
void TocModel::reset(shared_ptr<Toc const> toc)
{
toc_ = &toc;
toc_ = toc;
if (toc_->empty()) {
maxdepth_ = 0;
mindepth_ = 0;
@ -364,7 +366,7 @@ void TocModels::reset(BufferView const * bv)
iterator mod_it = models_.find(type);
if (mod_it == models_.end())
mod_it = models_.insert(type, new TocModel(this));
mod_it.value()->reset(*it->second);
mod_it.value()->reset(it->second);
// Fill in the names_ model.
QString const gui_name = guiName(it->first, bv->buffer().params());

View File

@ -12,6 +12,8 @@
#ifndef TOCMODEL_H
#define TOCMODEL_H
#include "support/shared_ptr.h"
#include <QHash>
#include <QSortFilterProxyModel>
@ -36,7 +38,7 @@ public:
///
TocModel(QObject * parent);
///
void reset(Toc const & toc);
void reset(shared_ptr<Toc const>);
///
void reset();
///
@ -68,7 +70,7 @@ private:
///
bool is_sorted_;
///
Toc const * toc_;
shared_ptr<Toc const> toc_;
///
int maxdepth_;
///

View File

@ -0,0 +1,94 @@
/**
* \file InsetCaptionable.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Alejandro Aguilar Sierra
* \author Jürgen Vigna
* \author Lars Gullik Bjønnes
* \author Guillaume Munch
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "InsetCaptionable.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "BufferView.h"
#include "FloatList.h"
#include "TextClass.h"
#include "TocBackend.h"
using namespace std;
namespace lyx {
void InsetCaptionable::setCaptionType(std::string const & type)
{
caption_type_ = type.empty() ? "senseless" : type;
}
/// common to InsetFloat and InsetWrap
docstring InsetCaptionable::floatName(string const & type) const
{
BufferParams const & bp = buffer().params();
FloatList const & floats = bp.documentClass().floats();
FloatList::const_iterator it = floats[type];
// FIXME UNICODE
return (it == floats.end()) ? from_ascii(type) : bp.B_(it->second.name());
}
void InsetCaptionable::addToToc(DocIterator const & cpit, bool output_active) const
{
DocIterator pit = cpit;
pit.push_back(CursorSlice(const_cast<InsetCaptionable &>(*this)));
docstring str;
int length = output_active ? INT_MAX : TOC_ENTRY_LENGTH;
text().forOutliner(str, length);
shared_ptr<TocBuilder> b = buffer().tocBackend().builder(caption_type_);
b->pushItem(pit, str, output_active);
// Proceed with the rest of the inset.
InsetCollapsable::addToToc(cpit, output_active);
b->pop();
}
void InsetCaptionable::updateBuffer(ParIterator const & it, UpdateType utype)
{
Counters & cnts =
buffer().masterBuffer()->params().documentClass().counters();
string const saveflt = cnts.current_float();
bool const savesubflt = cnts.isSubfloat();
if (utype == OutputUpdate) {
// counters are local to the float
cnts.saveLastCounter();
}
bool const subflt = hasSubCaptions(it);
// floats can only embed subfloats of their own kind
if (subflt && !saveflt.empty() && saveflt != "senseless")
setCaptionType(saveflt);
// Tell captions what the current float is
cnts.current_float(caption_type_);
cnts.isSubfloat(subflt);
InsetCollapsable::updateBuffer(it, utype);
// Restore counters
cnts.current_float(saveflt);
if (utype == OutputUpdate)
cnts.restoreLastCounter();
cnts.isSubfloat(savesubflt);
}
bool InsetCaptionable::insetAllowed(InsetCode c) const
{
return (c == CAPTION_CODE) || InsetCollapsable::insetAllowed(c);
}
} // namespace lyx

View File

@ -0,0 +1,54 @@
// -*- C++ -*-
/**
* \file InsetCaptionable.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Alejandro Aguilar Sierra
* \author Jürgen Vigna
* \author Lars Gullik Bjønnes
* \author Guillaume Munch
*
* Full author contact details are available in file CREDITS.
*/
#ifndef INSET_CAPTIONABLE_H
#define INSET_CAPTIONABLE_H
#include "InsetCollapsable.h"
namespace lyx {
class InsetCaptionable : public InsetCollapsable
{
public:
InsetCaptionable(Buffer * buffer)
: InsetCollapsable(buffer), caption_type_("senseless") {}
InsetCaptionable(Buffer * buffer, std::string const & type)
: InsetCollapsable(buffer), caption_type_(type) {}
///
std::string const & captionType() const { return caption_type_; }
///
docstring floatName(std::string const & type) const;
///
protected:
///
virtual void setCaptionType(std::string const & type);
/// are our captions subcaptions?
virtual bool hasSubCaptions(ParIterator const &) const { return false; }
///
void addToToc(DocIterator const & di, bool output_active) const;
/// Update the counters of this inset and of its contents
void updateBuffer(ParIterator const &, UpdateType);
///
bool insetAllowed(InsetCode) const;
private:
///
std::string caption_type_;
};
} // namespace lyx
#endif // INSET_CAPTIONABLE_H

View File

@ -15,18 +15,15 @@
#include "InsetCollapsable.h"
#include "Buffer.h"
#include "BufferParams.h"
#include "BufferView.h"
#include "Cursor.h"
#include "Dimension.h"
#include "FloatList.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
#include "InsetLayout.h"
#include "Lexer.h"
#include "MetricsInfo.h"
#include "OutputParams.h"
#include "TextClass.h"
#include "frontends/FontMetrics.h"
#include "frontends/Painter.h"
@ -602,16 +599,6 @@ void InsetCollapsable::setStatus(Cursor & cur, CollapseStatus status)
}
docstring InsetCollapsable::floatName(string const & type) const
{
BufferParams const & bp = buffer().params();
FloatList const & floats = bp.documentClass().floats();
FloatList::const_iterator it = floats[type];
// FIXME UNICODE
return (it == floats.end()) ? from_ascii(type) : bp.B_(it->second.name());
}
InsetLayout::InsetDecoration InsetCollapsable::decoration() const
{
InsetLayout::InsetDecoration const dec = getLayout().decoration();

View File

@ -148,8 +148,6 @@ public:
std::string contextMenu(BufferView const & bv, int x, int y) const;
///
std::string contextMenuName() const;
///
docstring floatName(std::string const & type) const;
protected:
///
void doDispatch(Cursor & cur, FuncRequest & cmd);

View File

@ -30,7 +30,6 @@
#include "output_xhtml.h"
#include "ParIterator.h"
#include "TextClass.h"
#include "TocBackend.h"
#include "support/debug.h"
#include "support/docstream.h"
@ -114,9 +113,23 @@ namespace lyx {
//FIXME: why do we set in stone the type here?
InsetFloat::InsetFloat(Buffer * buf, string params_str)
: InsetCollapsable(buf)
: InsetCaptionable(buf)
{
string2params(params_str, params_);
setCaptionType(params_.type);
}
// Enforce equality of float type and caption type.
void InsetFloat::setCaptionType(std::string const & type)
{
InsetCaptionable::setCaptionType(type);
params_.type = captionType();
// check if the float type exists
if (buffer().params().documentClass().floats().typeExist(params_.type))
setLabel(_("float: ") + floatName(params_.type));
else
setLabel(bformat(_("ERROR: Unknown float type: %1$s"), from_utf8(params_.type)));
}
@ -129,7 +142,7 @@ docstring InsetFloat::layoutName() const
docstring InsetFloat::toolTip(BufferView const & bv, int x, int y) const
{
if (isOpen(bv))
return InsetCollapsable::toolTip(bv, x, y);
return InsetCaptionable::toolTip(bv, x, y);
OutputParams rp(&buffer().params().encoding());
return getCaptionText(rp);
@ -152,10 +165,8 @@ void InsetFloat::doDispatch(Cursor & cur, FuncRequest & cmd)
params_.sideways = params.sideways;
}
setNewLabel();
if (params_.type != params.type) {
params_.type = params.type;
cur.forceBufferUpdate();
}
if (params_.type != params.type)
setCaptionType(params.type);
// what we really want here is a TOC update, but that means
// a full buffer update
cur.forceBufferUpdate();
@ -168,7 +179,7 @@ void InsetFloat::doDispatch(Cursor & cur, FuncRequest & cmd)
}
default:
InsetCollapsable::doDispatch(cur, cmd);
InsetCaptionable::doDispatch(cur, cmd);
break;
}
}
@ -185,7 +196,7 @@ bool InsetFloat::getStatus(Cursor & cur, FuncRequest const & cmd,
return true;
case LFUN_INSET_SETTINGS:
if (InsetCollapsable::getStatus(cur, cmd, flag)) {
if (InsetCaptionable::getStatus(cur, cmd, flag)) {
flag.setEnabled(flag.enabled() && !params_.subfloat);
return true;
} else
@ -198,62 +209,25 @@ bool InsetFloat::getStatus(Cursor & cur, FuncRequest const & cmd,
}
default:
return InsetCollapsable::getStatus(cur, cmd, flag);
return InsetCaptionable::getStatus(cur, cmd, flag);
}
}
void InsetFloat::addToToc(DocIterator const & cpit, bool output_active) const
bool InsetFloat::hasSubCaptions(ParIterator const & it) const
{
string const & type = params().type;
DocIterator pit = cpit;
pit.push_back(CursorSlice(const_cast<InsetFloat &>(*this)));
docstring str;
int length = output_active ? INT_MAX : TOC_ENTRY_LENGTH;
text().forOutliner(str, length);
shared_ptr<TocBuilder> builder = buffer().tocBackend().builder(type);
builder->pushItem(pit, str, output_active);
// Proceed with the rest of the inset.
InsetCollapsable::addToToc(cpit, output_active);
builder->pop();
}
void InsetFloat::updateBuffer(ParIterator const & it, UpdateType utype)
{
Counters & cnts =
buffer().masterBuffer()->params().documentClass().counters();
if (utype == OutputUpdate) {
// counters are local to the float
cnts.saveLastCounter();
}
string const saveflt = cnts.current_float();
bool const savesubflt = cnts.isSubfloat();
bool const subflt = (it.innerInsetOfType(FLOAT_CODE)
|| it.innerInsetOfType(WRAP_CODE));
// floats can only embed subfloats of their own kind
if (subflt)
params_.type = saveflt;
setSubfloat(subflt);
// Tell to captions what the current float is
cnts.current_float(params().type);
cnts.isSubfloat(subflt);
InsetCollapsable::updateBuffer(it, utype);
//reset afterwards
cnts.current_float(saveflt);
if (utype == OutputUpdate)
cnts.restoreLastCounter();
cnts.isSubfloat(savesubflt);
return (it.innerInsetOfType(FLOAT_CODE) || it.innerInsetOfType(WRAP_CODE));
}
void InsetFloatParams::write(ostream & os) const
{
os << type << '\n';
if (type.empty()) {
// Better this than creating a parse error. This in fact happens in the
// parameters dialog via InsetFloatParams::params2string.
os << "senseless" << '\n';
} else
os << type << '\n';
if (!placement.empty())
os << "placement " << placement << "\n";
@ -285,19 +259,15 @@ void InsetFloat::write(ostream & os) const
{
os << "Float ";
params_.write(os);
InsetCollapsable::write(os);
InsetCaptionable::write(os);
}
void InsetFloat::read(Lexer & lex)
{
params_.read(lex);
InsetCollapsable::read(lex);
// check if the float type exists
if (buffer().params().documentClass().floats().typeExist(params_.type))
setLabel(_("float: ") + floatName(params_.type));
else
setLabel(bformat(_("ERROR: Unknown float type: %1$s"), from_utf8(params_.type)));
InsetCaptionable::read(lex);
setCaptionType(params_.type);
}
@ -314,7 +284,7 @@ void InsetFloat::validate(LaTeXFeatures & features) const
features.useFloat(params_.type, features.inFloat());
features.inFloat(true);
InsetCollapsable::validate(features);
InsetCaptionable::validate(features);
features.inFloat(false);
}
@ -460,7 +430,7 @@ bool InsetFloat::insetAllowed(InsetCode code) const
case MARGIN_CODE:
return false;
default:
return InsetCollapsable::insetAllowed(code);
return InsetCaptionable::insetAllowed(code);
}
}

View File

@ -13,7 +13,7 @@
#ifndef INSET_FLOAT_H
#define INSET_FLOAT_H
#include "InsetCollapsable.h"
#include "InsetCaptionable.h"
namespace lyx {
@ -22,7 +22,7 @@ class InsetFloatParams
{
public:
///
InsetFloatParams() : wide(false), sideways(false), subfloat(false) {}
InsetFloatParams() : type("senseless"), wide(false), sideways(false), subfloat(false) {}
///
void write(std::ostream & os) const;
///
@ -48,12 +48,10 @@ public:
/////////////////////////////////////////////////////////////////////////
/// Used for "floating" objects like tables, figures etc.
class InsetFloat : public InsetCollapsable
class InsetFloat : public InsetCaptionable
{
public:
///
InsetFloat(Buffer * buffer, std::string params_str);
///
static void string2params(std::string const &, InsetFloatParams &);
///
@ -71,6 +69,8 @@ public:
///
bool allowsCaptionVariation(std::string const &) const;
private:
///
void setCaptionType(std::string const & type);
///
docstring layoutName() const;
///
@ -101,9 +101,7 @@ private:
///
bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;
///
void addToToc(DocIterator const & di, bool output_active) const;
/// Update the counters of this inset and of its contents
void updateBuffer(ParIterator const &, UpdateType);
bool hasSubCaptions(ParIterator const & it) const;
///
void doDispatch(Cursor & cur, FuncRequest & cmd);
///

View File

@ -51,7 +51,7 @@ namespace lyx {
InsetListings::InsetListings(Buffer * buf, InsetListingsParams const & par)
: InsetCollapsable(buf)
: InsetCaptionable(buf,"listing")
{
status_ = par.status();
}
@ -69,22 +69,6 @@ Inset::DisplayType InsetListings::display() const
}
void InsetListings::updateBuffer(ParIterator const & it, UpdateType utype)
{
Counters & cnts =
buffer().masterBuffer()->params().documentClass().counters();
string const saveflt = cnts.current_float();
// Tell to captions what the current float is
cnts.current_float("listing");
InsetCollapsable::updateBuffer(it, utype);
//reset afterwards
cnts.current_float(saveflt);
}
void InsetListings::write(ostream & os) const
{
os << "listings" << "\n";
@ -97,7 +81,7 @@ void InsetListings::write(ostream & os) const
os << "inline true\n";
else
os << "inline false\n";
InsetCollapsable::write(os);
InsetCaptionable::write(os);
}
@ -119,7 +103,7 @@ void InsetListings::read(Lexer & lex)
break;
}
}
InsetCollapsable::read(lex);
InsetCaptionable::read(lex);
}
@ -334,7 +318,7 @@ void InsetListings::doDispatch(Cursor & cur, FuncRequest & cmd)
break;
default:
InsetCollapsable::doDispatch(cur, cmd);
InsetCaptionable::doDispatch(cur, cmd);
break;
}
}
@ -356,7 +340,7 @@ bool InsetListings::getStatus(Cursor & cur, FuncRequest const & cmd,
}
}
default:
return InsetCollapsable::getStatus(cur, cmd, status);
return InsetCaptionable::getStatus(cur, cmd, status);
}
}
@ -377,7 +361,7 @@ void InsetListings::validate(LaTeXFeatures & features) const
string param_string = params().params();
if (param_string.find("\\color") != string::npos)
features.require("color");
InsetCollapsable::validate(features);
InsetCaptionable::validate(features);
}

View File

@ -25,8 +25,8 @@ class LaTeXFeatures;
//
/////////////////////////////////////////////////////////////////////////
/// A collapsable text inset for program listings.
class InsetListings : public InsetCollapsable
/// A captionable and collapsable text inset for program listings.
class InsetListings : public InsetCaptionable
{
public:
///
@ -48,8 +48,6 @@ private:
DisplayType display() const;
///
docstring layoutName() const { return from_ascii("Listings"); }
// Update the counters of this inset and of its contents
void updateBuffer(ParIterator const &, UpdateType);
///
void write(std::ostream & os) const;
///

View File

@ -12,7 +12,7 @@
#ifndef INSETLISTINGSPARAMS_H
#define INSETLISTINGSPARAMS_H
#include "InsetCollapsable.h"
#include "InsetCaptionable.h"
#include <map>

View File

@ -43,10 +43,9 @@ using namespace std;
namespace lyx {
InsetWrap::InsetWrap(Buffer * buf, string const & type)
: InsetCollapsable(buf)
: InsetCaptionable(buf)
{
setLabel(_("wrap: ") + floatName(type));
params_.type = type;
setCaptionType(type);
params_.lines = 0;
params_.placement = "o";
params_.overhang = Length(0, Length::PCW);
@ -60,6 +59,15 @@ InsetWrap::~InsetWrap()
}
// Enforce equality of float type and caption type.
void InsetWrap::setCaptionType(std::string const & type)
{
InsetCaptionable::setCaptionType(type);
params_.type = captionType();
setLabel(_("wrap: ") + floatName(type));
}
docstring InsetWrap::layoutName() const
{
return "Wrap:" + from_utf8(params_.type);
@ -69,7 +77,7 @@ docstring InsetWrap::layoutName() const
docstring InsetWrap::toolTip(BufferView const & bv, int x, int y) const
{
if (isOpen(bv))
return InsetCollapsable::toolTip(bv, x, y);
return InsetCaptionable::toolTip(bv, x, y);
OutputParams rp(&buffer().params().encoding());
docstring caption_tip = getCaptionText(rp);
if (!caption_tip.empty())
@ -97,7 +105,7 @@ void InsetWrap::doDispatch(Cursor & cur, FuncRequest & cmd)
break;
default:
InsetCollapsable::doDispatch(cur, cmd);
InsetCaptionable::doDispatch(cur, cmd);
break;
}
}
@ -113,31 +121,14 @@ bool InsetWrap::getStatus(Cursor & cur, FuncRequest const & cmd,
return true;
default:
return InsetCollapsable::getStatus(cur, cmd, flag);
return InsetCaptionable::getStatus(cur, cmd, flag);
}
}
void InsetWrap::updateBuffer(ParIterator const & it, UpdateType utype)
{
setLabel(_("wrap: ") + floatName(params_.type));
Counters & cnts =
buffer().masterBuffer()->params().documentClass().counters();
if (utype == OutputUpdate) {
// counters are local to the wrap
cnts.saveLastCounter();
}
string const saveflt = cnts.current_float();
// Tell to captions what the current float is
cnts.current_float(params().type);
InsetCollapsable::updateBuffer(it, utype);
// reset afterwards
cnts.current_float(saveflt);
if (utype == OutputUpdate)
cnts.restoreLastCounter();
InsetCaptionable::updateBuffer(it, utype);
}
@ -164,14 +155,14 @@ void InsetWrapParams::read(Lexer & lex)
void InsetWrap::write(ostream & os) const
{
params_.write(os);
InsetCollapsable::write(os);
InsetCaptionable::write(os);
}
void InsetWrap::read(Lexer & lex)
{
params_.read(lex);
InsetCollapsable::read(lex);
InsetCaptionable::read(lex);
}
@ -179,7 +170,7 @@ void InsetWrap::validate(LaTeXFeatures & features) const
{
features.require("wrapfig");
features.inFloat(true);
InsetCollapsable::validate(features);
InsetCaptionable::validate(features);
features.inFloat(false);
}
@ -248,7 +239,7 @@ bool InsetWrap::insetAllowed(InsetCode code) const
case MARGIN_CODE:
return false;
default:
return InsetCollapsable::insetAllowed(code);
return InsetCaptionable::insetAllowed(code);
}
}

View File

@ -12,7 +12,7 @@
#ifndef INSETWRAP_H
#define INSETWRAP_H
#include "InsetCollapsable.h"
#include "InsetCaptionable.h"
#include "Length.h"
@ -41,7 +41,7 @@ public:
/** The wrap inset
*/
class InsetWrap : public InsetCollapsable {
class InsetWrap : public InsetCaptionable {
public:
///
InsetWrap(Buffer *, std::string const &);
@ -54,6 +54,8 @@ public:
///
static std::string params2string(InsetWrapParams const &);
private:
///
void setCaptionType(std::string const & type);
///
void write(std::ostream & os) const;
///
@ -79,7 +81,7 @@ private:
bool showInsetDialog(BufferView *) const;
///
bool getStatus(Cursor &, FuncRequest const &, FuncStatus &) const;
/// Update the counters of this inset and of its contents
/// Update the label
void updateBuffer(ParIterator const &, UpdateType);
///
void doDispatch(Cursor & cur, FuncRequest & cmd);