lyx_mirror/src/frontends/qt4/GuiTabular.cpp
Guillaume Munch c9f7ce0a7a New LFUN tabular-feature (#9794)
The tabular-features LFUN was merged with "inset-modify tabular" when
simplifying the tabular dialog at b5049e7. This choice later indirectly caused a
few regressions (#7308, #9794).

I reintroduce tabular-feature to allow more flexibility for user
commands, whereas "inset-modify tabular" is now reserved for the tabular
dialog. In particular, inset-modify tabular is no longer caught by math grid
insets. The name tabular-feature is kept to avoid renaming icons.

Known issues:

* After successfully applying a tabular command, the cursor is truncated to the
  table.

* Note that the tabular dialog still has similar issues that are inherited from
  the achitecture of the dialog menu. For instance the pref change can be
  mis-dispatched to an inset inside a cell and cause an error, for instance:

    Lexer.cpp (934): Missing 'Note'-tag in InsetNote::string2params. Got
    tabular instead. Line: 0

  Maybe the inset-modify LFUN should be modified to treat commands coming from
  the wrong dialog (by checking the type) as unknown and undispatched so that
  the parent can get it. In that case a non AtPoint variant of inset-modify
  could be reintroduced in order to generalise tabular-feature. See:
  http://mid.gmane.org/n4rdk1$efj$1@ger.gmane.org
2016-01-27 18:20:37 +01:00

1081 lines
34 KiB
C++

/**
* \file GuiTabular.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author John Levon
* \author Jürgen Spitzmüller
* \author Herbert Voß
* \author Uwe Stöhr
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "GuiTabular.h"
#include "GuiApplication.h"
#include "GuiSetBorder.h"
#include "GuiView.h"
#include "LengthCombo.h"
#include "qt_helpers.h"
#include "Validator.h"
#include "BufferView.h"
#include "Cursor.h"
#include "FuncRequest.h"
#include "FuncStatus.h"
#include "LyX.h"
#include "LyXRC.h"
#include "insets/InsetTabular.h"
#include "support/convert.h"
#include "support/debug.h"
#include <QCheckBox>
#include <QPushButton>
#include <QRadioButton>
#include <QLineEdit>
using namespace std;
namespace lyx {
namespace frontend {
GuiTabular::GuiTabular(QWidget * parent)
: InsetParamsWidget(parent)
{
setupUi(this);
tabularWidthED->setValidator(unsignedLengthValidator(tabularWidthED));
columnWidthED->setValidator(unsignedLengthValidator(columnWidthED));
multirowOffsetED->setValidator(new LengthValidator(multirowOffsetED));
topspaceED->setValidator(new LengthValidator(topspaceED));
bottomspaceED->setValidator(new LengthValidator(bottomspaceED));
interlinespaceED->setValidator(new LengthValidator(interlinespaceED));
tabularWidthUnitLC->setCurrentItem(Length::defaultUnit());
columnWidthUnitLC->setCurrentItem(Length::defaultUnit());
multirowOffsetUnitLC->setCurrentItem(Length::defaultUnit());
topspaceUnitLC->setCurrentItem(Length::defaultUnit());
bottomspaceUnitLC->setCurrentItem(Length::defaultUnit());
interlinespaceUnitLC->setCurrentItem(Length::defaultUnit());
connect(topspaceED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(topspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
this, SLOT(checkEnabled()));
connect(bottomspaceED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(bottomspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
this, SLOT(checkEnabled()));
connect(interlinespaceED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(interlinespaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
this, SLOT(checkEnabled()));
connect(booktabsRB, SIGNAL(clicked(bool)),
this, SLOT(checkEnabled()));
connect(borderDefaultRB, SIGNAL(clicked(bool)),
this, SLOT(checkEnabled()));
connect(borderSetPB, SIGNAL(clicked()),
this, SLOT(borderSet_clicked()));
connect(borderUnsetPB, SIGNAL(clicked()),
this, SLOT(borderUnset_clicked()));
connect(hAlignCO, SIGNAL(activated(int)),
this, SLOT(checkEnabled()));
connect(vAlignCO, SIGNAL(activated(int)),
this, SLOT(checkEnabled()));
connect(multicolumnCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(multirowCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(multirowOffsetED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(multirowOffsetUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
this, SLOT(checkEnabled()));
connect(newpageCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(headerStatusCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(headerBorderAboveCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(headerBorderBelowCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(firstheaderStatusCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(firstheaderBorderAboveCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(firstheaderBorderBelowCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(firstheaderNoContentsCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(footerStatusCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(footerBorderAboveCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(footerBorderBelowCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(lastfooterStatusCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(lastfooterBorderAboveCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(lastfooterBorderBelowCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(lastfooterNoContentsCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(captionStatusCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(specialAlignmentED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(columnWidthED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(topSet(bool)),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(bottomSet(bool)),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(rightSet(bool)),
this, SLOT(checkEnabled()));
connect(borders, SIGNAL(leftSet(bool)),
this, SLOT(checkEnabled()));
connect(rotateTabularCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(rotateTabularAngleSB, SIGNAL(valueChanged(int)),
this, SLOT(checkEnabled()));
connect(rotateCellCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(rotateCellAngleSB, SIGNAL(valueChanged(int)),
this, SLOT(checkEnabled()));
connect(TableAlignCO, SIGNAL(activated(int)),
this, SLOT(checkEnabled()));
connect(longTabularCB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(leftRB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(centerRB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(rightRB, SIGNAL(clicked()),
this, SLOT(checkEnabled()));
connect(tabularWidthED, SIGNAL(textEdited(const QString &)),
this, SLOT(checkEnabled()));
decimalPointED->setInputMask("X; ");
decimalPointED->setMaxLength(1);
// initialize the length validator
addCheckedWidget(columnWidthED, columnWidthLA);
addCheckedWidget(multirowOffsetED, multirowOffsetLA);
addCheckedWidget(topspaceED, topspaceLA);
addCheckedWidget(bottomspaceED, bottomspaceLA);
addCheckedWidget(interlinespaceED, interlinespaceLA);
addCheckedWidget(tabularWidthED, tabularWidthLA);
}
void GuiTabular::on_topspaceCO_activated(int index)
{
bool const enable = (index == 2);
topspaceED->setEnabled(enable);
topspaceUnitLC->setEnabled(enable);
}
void GuiTabular::on_bottomspaceCO_activated(int index)
{
bool const enable = (index == 2);
bottomspaceED->setEnabled(enable);
bottomspaceUnitLC->setEnabled(enable);
}
void GuiTabular::on_interlinespaceCO_activated(int index)
{
bool const enable = (index == 2);
interlinespaceED->setEnabled(enable);
interlinespaceUnitLC->setEnabled(enable);
}
void GuiTabular::enableWidgets() const
{
// if there is a LaTeX argument, the width and alignment will be overwritten
// therefore disable them in this case
columnWidthED->setEnabled(specialAlignmentED->text().isEmpty());
columnWidthUnitLC->setEnabled(specialAlignmentED->text().isEmpty());
// if the column has a width, multirows are always left-aligned
// therefore disable hAlignCB in this case
hAlignCO->setEnabled(!(multirowCB->isChecked()
&& !widgetsToLength(columnWidthED, columnWidthUnitLC).empty())
&& specialAlignmentED->text().isEmpty());
// decimal alignment is only possible for non-multicol and non-multirow cells
if ((multicolumnCB->isChecked() || multirowCB->isChecked())
&& hAlignCO->findData(toqstr("decimal")))
hAlignCO->removeItem(hAlignCO->findData(toqstr("decimal")));
else if (!multicolumnCB->isChecked() && !multirowCB->isChecked()
&& hAlignCO->findData(toqstr("decimal")) == -1)
hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
bool const dalign =
hAlignCO->itemData(hAlignCO->currentIndex()).toString() == QString("decimal");
decimalPointED->setEnabled(dalign);
decimalLA->setEnabled(dalign);
bool const setwidth = TableAlignCO->currentText() == qt_("Middle")
&& !longTabularCB->isChecked();
tabularWidthLA->setEnabled(setwidth);
tabularWidthED->setEnabled(setwidth);
tabularWidthUnitLC->setEnabled(setwidth);
rotateTabularAngleSB->setEnabled(rotateTabularCB->isChecked());
rotateCellAngleSB->setEnabled(rotateCellCB->isChecked());
bool const enable_valign =
!multirowCB->isChecked()
&& !widgetsToLength(columnWidthED, columnWidthUnitLC).empty()
&& specialAlignmentED->text().isEmpty();
vAlignCO->setEnabled(enable_valign);
vAlignLA->setEnabled(enable_valign);
topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
topspaceUnitLC->setEnabled(topspaceCO->currentIndex() == 2);
bottomspaceED->setEnabled(bottomspaceCO->currentIndex() == 2);
bottomspaceUnitLC->setEnabled(bottomspaceCO->currentIndex() == 2);
interlinespaceED->setEnabled(interlinespaceCO->currentIndex() == 2);
interlinespaceUnitLC->setEnabled(interlinespaceCO->currentIndex() == 2);
// setting as longtable is not allowed when table is inside a float
bool const is_tabular_star = !tabularWidthED->text().isEmpty();
longTabularCB->setEnabled(!is_tabular_star && funcEnabled(Tabular::SET_LONGTABULAR));
bool const longtabular = longTabularCB->isChecked();
longtableGB->setEnabled(true);
newpageCB->setEnabled(longtabular);
alignmentGB->setEnabled(longtabular);
// longtables and tabular* cannot have a vertical alignment
TableAlignLA->setDisabled(is_tabular_star || longtabular);
TableAlignCO->setDisabled(is_tabular_star || longtabular);
// FIXME: This Dialog is really horrible, disabling/enabling a checkbox
// depending on the cursor position is very very unintuitive...
// We need some edit boxes to show which rows are header/footer/etc
// without having to move the cursor first.
headerStatusCB->setEnabled(longtabular
&& (headerStatusCB->isChecked() ?
funcEnabled(Tabular::UNSET_LTHEAD) :
funcEnabled(Tabular::SET_LTHEAD)));
headerBorderAboveCB->setEnabled(longtabular
&& headerStatusCB->isChecked());
headerBorderBelowCB->setEnabled(longtabular
&& headerStatusCB->isChecked());
// first header can only be suppressed when there is a header
// firstheader_suppressable_ is set in paramsToDialog
firstheaderNoContentsCB->setEnabled(longtabular && firstheader_suppressable_);
// check if setting a first header is allowed
// additionally check firstheaderNoContentsCB because when this is
// the case a first header makes no sense
firstheaderStatusCB->setEnabled((firstheaderStatusCB->isChecked() ?
funcEnabled(Tabular::UNSET_LTFIRSTHEAD) :
funcEnabled(Tabular::SET_LTFIRSTHEAD))
&& longtabular && !firstheaderNoContentsCB->isChecked());
firstheaderBorderAboveCB->setEnabled(longtabular
&& firstheaderStatusCB->isChecked());
firstheaderBorderBelowCB->setEnabled(longtabular
&& firstheaderStatusCB->isChecked());
footerStatusCB->setEnabled(longtabular
&& (footerStatusCB->isChecked() ?
funcEnabled(Tabular::UNSET_LTFOOT) :
funcEnabled(Tabular::SET_LTFOOT)));
footerBorderAboveCB->setEnabled(longtabular
&& footerBorderAboveCB->isChecked());
footerBorderBelowCB->setEnabled(longtabular
&& footerBorderAboveCB->isChecked());
// last footer can only be suppressed when there is a footer
// lastfooter_suppressable_ is set in paramsToDialog
lastfooterNoContentsCB->setEnabled(longtabular && lastfooter_suppressable_);
// check if setting a last footer is allowed
// additionally check lastfooterNoContentsCB because when this is
// the case a last footer makes no sense
lastfooterStatusCB->setEnabled((lastfooterStatusCB->isChecked() ?
funcEnabled(Tabular::UNSET_LTLASTFOOT) :
funcEnabled(Tabular::SET_LTLASTFOOT))
&& longtabular && !lastfooterNoContentsCB->isChecked());
lastfooterBorderAboveCB->setEnabled(longtabular
&& lastfooterBorderAboveCB->isChecked());
lastfooterBorderBelowCB->setEnabled(longtabular
&& lastfooterBorderAboveCB->isChecked());
captionStatusCB->setEnabled(funcEnabled(Tabular::TOGGLE_LTCAPTION)
&& longtabular);
multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN)
&& !dalign && !multirowCB->isChecked());
multirowCB->setEnabled(funcEnabled(Tabular::MULTIROW)
&& !dalign && !multicolumnCB->isChecked());
bool const enable_mr = multirowCB->isChecked();
multirowOffsetLA->setEnabled(enable_mr);
multirowOffsetED->setEnabled(enable_mr);
multirowOffsetUnitLC->setEnabled(enable_mr);
// Vertical lines cannot be set in formal tables
borders->setLeftEnabled(!booktabsRB->isChecked());
borders->setRightEnabled(!booktabsRB->isChecked());
}
void GuiTabular::checkEnabled()
{
enableWidgets();
changed();
}
void GuiTabular::borderSet_clicked()
{
borders->setTop(true);
borders->setBottom(true);
borders->setLeft(true);
borders->setRight(true);
// repaint the setborder widget
borders->update();
checkEnabled();
}
void GuiTabular::borderUnset_clicked()
{
borders->setTop(false);
borders->setBottom(false);
borders->setLeft(false);
borders->setRight(false);
// repaint the setborder widget
borders->update();
checkEnabled();
}
static void setParam(string & param_str, Tabular::Feature f, string const & arg = string())
{
param_str += ' ';
param_str += featureAsString(f) + ' ' + arg;
}
void GuiTabular::setHAlign(string & param_str) const
{
Tabular::Feature num = Tabular::ALIGN_LEFT;
Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
string const align =
fromqstr(hAlignCO->itemData(hAlignCO->currentIndex()).toString());
if (align == "left") {
num = Tabular::ALIGN_LEFT;
multi_num = Tabular::M_ALIGN_LEFT;
} else if (align == "center") {
num = Tabular::ALIGN_CENTER;
multi_num = Tabular::M_ALIGN_CENTER;
} else if (align == "right") {
num = Tabular::ALIGN_RIGHT;
multi_num = Tabular::M_ALIGN_RIGHT;
} else if (align == "justified") {
num = Tabular::ALIGN_BLOCK;
//multi_num: no equivalent
} else if (align == "decimal") {
num = Tabular::ALIGN_DECIMAL;
//multi_num: no equivalent
}
if (multicolumnCB->isChecked())
setParam(param_str, multi_num);
else
setParam(param_str, num);
}
void GuiTabular::setVAlign(string & param_str) const
{
int const align = vAlignCO->currentIndex();
enum VALIGN { TOP, MIDDLE, BOTTOM };
VALIGN v = TOP;
switch (align) {
case 0: v = TOP; break;
case 1: v = MIDDLE; break;
case 2: v = BOTTOM; break;
}
Tabular::Feature num = Tabular::VALIGN_MIDDLE;
Tabular::Feature multi_num = Tabular::M_VALIGN_MIDDLE;
switch (v) {
case TOP:
num = Tabular::VALIGN_TOP;
multi_num = Tabular::M_VALIGN_TOP;
break;
case MIDDLE:
num = Tabular::VALIGN_MIDDLE;
multi_num = Tabular::M_VALIGN_MIDDLE;
break;
case BOTTOM:
num = Tabular::VALIGN_BOTTOM;
multi_num = Tabular::M_VALIGN_BOTTOM;
break;
}
if (multicolumnCB->isChecked() || multirowCB->isChecked())
setParam(param_str, multi_num);
else
setParam(param_str, num);
}
void GuiTabular::setTableAlignment(string & param_str) const
{
int const align = TableAlignCO->currentIndex();
switch (align) {
case 0: setParam(param_str, Tabular::TABULAR_VALIGN_TOP);
break;
case 1: setParam(param_str, Tabular::TABULAR_VALIGN_MIDDLE);
break;
case 2: setParam(param_str, Tabular::TABULAR_VALIGN_BOTTOM);
break;
}
}
docstring GuiTabular::dialogToParams() const
{
string param_str = "tabular";
// table width
string tabwidth = widgetsToLength(tabularWidthED, tabularWidthUnitLC);
if (tabwidth.empty())
tabwidth = "0pt";
setParam(param_str, Tabular::SET_TABULAR_WIDTH, tabwidth);
// apply the fixed width values
// this must be done before applying the column alignment
// because its value influences the alignment of multirow cells
string width = widgetsToLength(columnWidthED, columnWidthUnitLC);
if (width.empty())
width = "0pt";
if (multicolumnCB->isChecked())
setParam(param_str, Tabular::SET_MPWIDTH, width);
else
setParam(param_str, Tabular::SET_PWIDTH, width);
// apply the column alignment
// multirows inherit the alignment from the column; if a column width
// is set, multirows are always left-aligned so that in this case
// its alignment must not be applied (see bug #8084)
if (!(multirowCB->isChecked() && width != "0pt"))
setHAlign(param_str);
// SET_DECIMAL_POINT must come after setHAlign() (ALIGN_DECIMAL)
string decimal_point = fromqstr(decimalPointED->text());
if (decimal_point.empty())
decimal_point = lyxrc.default_decimal_point;
setParam(param_str, Tabular::SET_DECIMAL_POINT, decimal_point);
setVAlign(param_str);
setTableAlignment(param_str);
//
if (booktabsRB->isChecked())
setParam(param_str, Tabular::SET_BOOKTABS);
else
setParam(param_str, Tabular::UNSET_BOOKTABS);
//
switch (topspaceCO->currentIndex()) {
case 0:
setParam(param_str, Tabular::SET_TOP_SPACE, "none");
break;
case 1:
setParam(param_str, Tabular::SET_TOP_SPACE, "default");
break;
case 2:
if (!topspaceED->text().isEmpty())
setParam(param_str, Tabular::SET_TOP_SPACE,
widgetsToLength(topspaceED, topspaceUnitLC));
break;
}
//
switch (bottomspaceCO->currentIndex()) {
case 0:
setParam(param_str, Tabular::SET_BOTTOM_SPACE, "none");
break;
case 1:
setParam(param_str, Tabular::SET_BOTTOM_SPACE, "default");
break;
case 2:
if (!bottomspaceED->text().isEmpty())
setParam(param_str, Tabular::SET_BOTTOM_SPACE,
widgetsToLength(bottomspaceED,
bottomspaceUnitLC));
break;
}
//
switch (interlinespaceCO->currentIndex()) {
case 0:
setParam(param_str, Tabular::SET_INTERLINE_SPACE, "none");
break;
case 1:
setParam(param_str, Tabular::SET_INTERLINE_SPACE, "default");
break;
case 2:
if (!interlinespaceED->text().isEmpty())
setParam(param_str, Tabular::SET_INTERLINE_SPACE,
widgetsToLength(interlinespaceED,
interlinespaceUnitLC));
break;
}
//
if (borders->getTop() && borders->getBottom() && borders->getLeft()
&& borders->getRight())
setParam(param_str, Tabular::SET_ALL_LINES);
else if (!borders->getTop() && !borders->getBottom() && !borders->getLeft()
&& !borders->getRight())
setParam(param_str, Tabular::UNSET_ALL_LINES);
else {
setParam(param_str, Tabular::SET_LINE_LEFT,
borders->getLeft() ? "true" : "false");
setParam(param_str, Tabular::SET_LINE_RIGHT,
borders->getRight() ? "true" : "false");
setParam(param_str, Tabular::SET_LINE_TOP,
borders->getTop() ? "true" : "false");
setParam(param_str, Tabular::SET_LINE_BOTTOM,
borders->getBottom() ? "true" : "false");
}
// apply the special alignment
string special = fromqstr(specialAlignmentED->text());
if (special.empty())
special = "none";
if (multicolumnCB->isChecked())
setParam(param_str, Tabular::SET_SPECIAL_MULTICOLUMN, special);
else
setParam(param_str, Tabular::SET_SPECIAL_COLUMN, special);
//
if (multicolumnCB->isChecked())
setParam(param_str, Tabular::SET_MULTICOLUMN);
else
setParam(param_str, Tabular::UNSET_MULTICOLUMN);
// apply the multirow offset
string mroffset = widgetsToLength(multirowOffsetED, multirowOffsetUnitLC);
if (mroffset.empty())
mroffset = "0pt";
if (multirowCB->isChecked())
setParam(param_str, Tabular::SET_MROFFSET, mroffset);
//
if (multirowCB->isChecked())
setParam(param_str, Tabular::SET_MULTIROW);
else
setParam(param_str, Tabular::UNSET_MULTIROW);
// store the table rotation angle
string const tabular_angle = convert<string>(rotateTabularAngleSB->value());
if (rotateTabularCB->isChecked())
setParam(param_str, Tabular::SET_ROTATE_TABULAR, tabular_angle);
else
setParam(param_str, Tabular::UNSET_ROTATE_TABULAR, tabular_angle);
// store the cell rotation angle
string const cell_angle = convert<string>(rotateCellAngleSB->value());
if (rotateCellCB->isChecked())
setParam(param_str, Tabular::SET_ROTATE_CELL, cell_angle);
else
setParam(param_str, Tabular::UNSET_ROTATE_CELL, cell_angle);
//
if (longTabularCB->isChecked())
setParam(param_str, Tabular::SET_LONGTABULAR);
else
setParam(param_str, Tabular::UNSET_LONGTABULAR);
//
if (newpageCB->isChecked())
setParam(param_str, Tabular::SET_LTNEWPAGE);
else
setParam(param_str, Tabular::UNSET_LTNEWPAGE);
//
if (captionStatusCB->isChecked())
setParam(param_str, Tabular::SET_LTCAPTION);
else
setParam(param_str, Tabular::UNSET_LTCAPTION);
//
if (headerStatusCB->isChecked())
setParam(param_str, Tabular::SET_LTHEAD, "none");
else
setParam(param_str, Tabular::UNSET_LTHEAD, "none");
//
if (headerBorderAboveCB->isChecked())
setParam(param_str, Tabular::SET_LTHEAD, "dl_above");
else
setParam(param_str, Tabular::UNSET_LTHEAD, "dl_above");
//
if (headerBorderBelowCB->isChecked())
setParam(param_str, Tabular::SET_LTHEAD, "dl_below");
else
setParam(param_str, Tabular::UNSET_LTHEAD, "dl_below");
if (firstheaderBorderAboveCB->isChecked())
setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_above");
else
setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_above");
if (firstheaderBorderBelowCB->isChecked())
setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_below");
else
setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_below");
if (firstheaderStatusCB->isChecked())
setParam(param_str, Tabular::SET_LTFIRSTHEAD, "none");
else
setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "none");
if (firstheaderNoContentsCB->isChecked())
setParam(param_str, Tabular::SET_LTFIRSTHEAD, "empty");
else
setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "empty");
if (footerStatusCB->isChecked())
setParam(param_str, Tabular::SET_LTFOOT, "none");
else
setParam(param_str, Tabular::UNSET_LTFOOT, "none");
if (footerBorderAboveCB->isChecked())
setParam(param_str, Tabular::SET_LTFOOT, "dl_above");
else
setParam(param_str, Tabular::UNSET_LTFOOT, "dl_above");
if (footerBorderBelowCB->isChecked())
setParam(param_str, Tabular::SET_LTFOOT, "dl_below");
else
setParam(param_str, Tabular::UNSET_LTFOOT, "dl_below");
if (lastfooterStatusCB->isChecked())
setParam(param_str, Tabular::SET_LTLASTFOOT, "none");
else
setParam(param_str, Tabular::UNSET_LTLASTFOOT, "none");
if (lastfooterBorderAboveCB->isChecked())
setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_above");
else
setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_above");
if (lastfooterBorderBelowCB->isChecked())
setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_below");
else
setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_below");
if (lastfooterNoContentsCB->isChecked())
setParam(param_str, Tabular::SET_LTLASTFOOT, "empty");
else
setParam(param_str, Tabular::UNSET_LTLASTFOOT, "empty");
if (leftRB->isChecked())
setParam(param_str, Tabular::LONGTABULAR_ALIGN_LEFT);
else if (centerRB->isChecked())
setParam(param_str, Tabular::LONGTABULAR_ALIGN_CENTER);
else if (rightRB->isChecked())
setParam(param_str, Tabular::LONGTABULAR_ALIGN_RIGHT);
return from_utf8(param_str);
}
static Length getColumnPWidth(Tabular const & t, size_t cell)
{
return t.column_info[t.cellColumn(cell)].p_width;
}
static Length getMColumnPWidth(Tabular const & t, size_t cell)
{
if (t.isMultiColumn(cell) || t.isMultiRow(cell))
return t.cellInfo(cell).p_width;
return Length();
}
static Length getMROffset(Tabular const & t, size_t cell)
{
if (t.isMultiRow(cell))
return t.cellInfo(cell).mroffset;
return Length();
}
static docstring getAlignSpecial(Tabular const & t, size_t cell, int what)
{
if (what == Tabular::SET_SPECIAL_MULTICOLUMN)
return t.cellInfo(cell).align_special;
return t.column_info[t.cellColumn(cell)].align_special;
}
void GuiTabular::paramsToDialog(Inset const * inset)
{
InsetTabular const * itab = static_cast<InsetTabular const *>(inset);
// Copy Tabular of current inset.
Tabular const & tabular = itab->tabular;
BufferView const * bv = guiApp->currentView()->currentBufferView();
size_t const cell = bv->cursor().idx();
Tabular::row_type const row = tabular.cellRow(cell);
Tabular::col_type const col = tabular.cellColumn(cell);
tabularRowED->setText(QString::number(row + 1));
tabularColumnED->setText(QString::number(col + 1));
bool const multicol = tabular.isMultiColumn(cell);
multicolumnCB->setChecked(multicol);
bool const multirow = tabular.isMultiRow(cell);
multirowCB->setChecked(multirow);
rotateCellCB->setChecked(tabular.getRotateCell(cell) != 0);
if (rotateCellCB->isChecked()) {
if (tabular.getRotateCell(cell) != 0)
rotateCellAngleSB->setValue(tabular.getRotateCell(cell));
else
rotateCellAngleSB->setValue(90);
}
rotateTabularCB->setChecked(tabular.rotate != 0);
if (rotateTabularCB->isChecked())
rotateTabularAngleSB->setValue(tabular.rotate != 0 ? tabular.rotate : 90);
longTabularCB->setChecked(tabular.is_long_tabular);
borders->setTop(tabular.topLine(cell));
borders->setBottom(tabular.bottomLine(cell));
borders->setLeft(tabular.leftLine(cell));
borders->setRight(tabular.rightLine(cell));
// repaint the setborder widget
borders->update();
Length::UNIT const default_unit = Length::defaultUnit();
///////////////////////////////////
// Set width and alignment
Length const tabwidth = tabular.tabularWidth();
if (tabwidth.zero()
&& !(tabularWidthED->hasFocus() && tabularWidthED->text() == "0"))
tabularWidthED->clear();
else
lengthToWidgets(tabularWidthED, tabularWidthUnitLC,
tabwidth.asString(), default_unit);
Length pwidth;
docstring special;
if (multicol) {
special = getAlignSpecial(tabular, cell,
Tabular::SET_SPECIAL_MULTICOLUMN);
pwidth = getMColumnPWidth(tabular, cell);
} else {
special = getAlignSpecial(tabular, cell,
Tabular::SET_SPECIAL_COLUMN);
pwidth = getColumnPWidth(tabular, cell);
}
string colwidth;
if (pwidth.zero()
&& !(columnWidthED->hasFocus() && columnWidthED->text() == "0"))
columnWidthED->clear();
else {
colwidth = pwidth.asString();
lengthToWidgets(columnWidthED, columnWidthUnitLC,
colwidth, default_unit);
}
Length mroffset;
if (multirow)
mroffset = getMROffset(tabular, cell);
string offset;
if (mroffset.zero()
&& !(multirowOffsetED->hasFocus() && multirowOffsetED->text() == "0"))
multirowOffsetED->clear();
else {
offset = mroffset.asString();
lengthToWidgets(multirowOffsetED, multirowOffsetUnitLC,
offset, default_unit);
}
specialAlignmentED->setText(toqstr(special));
///////////////////////////////////
borderDefaultRB->setChecked(!tabular.use_booktabs);
booktabsRB->setChecked(tabular.use_booktabs);
if (tabular.row_info[row].top_space.empty()
&& !tabular.row_info[row].top_space_default) {
topspaceCO->setCurrentIndex(0);
} else if (tabular.row_info[row].top_space_default) {
topspaceCO->setCurrentIndex(1);
} else {
topspaceCO->setCurrentIndex(2);
lengthToWidgets(topspaceED,
topspaceUnitLC,
tabular.row_info[row].top_space.asString(),
default_unit);
}
if (tabular.row_info[row].bottom_space.empty()
&& !tabular.row_info[row].bottom_space_default) {
bottomspaceCO->setCurrentIndex(0);
} else if (tabular.row_info[row].bottom_space_default) {
bottomspaceCO->setCurrentIndex(1);
} else {
bottomspaceCO->setCurrentIndex(2);
lengthToWidgets(bottomspaceED,
bottomspaceUnitLC,
tabular.row_info[row].bottom_space.asString(),
default_unit);
}
if (tabular.row_info[row].interline_space.empty()
&& !tabular.row_info[row].interline_space_default) {
interlinespaceCO->setCurrentIndex(0);
} else if (tabular.row_info[row].interline_space_default) {
interlinespaceCO->setCurrentIndex(1);
} else {
interlinespaceCO->setCurrentIndex(2);
lengthToWidgets(interlinespaceED,
interlinespaceUnitLC,
tabular.row_info[row].interline_space.asString(),
default_unit);
}
hAlignCO->clear();
hAlignCO->addItem(qt_("Left"), toqstr("left"));
hAlignCO->addItem(qt_("Center"), toqstr("center"));
hAlignCO->addItem(qt_("Right"), toqstr("right"));
if (!multicol && !pwidth.zero())
hAlignCO->addItem(qt_("Justified"), toqstr("justified"));
if (!multicol && !multirow)
hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
string align;
switch (tabular.getAlignment(cell)) {
case LYX_ALIGN_LEFT:
align = "left";
break;
case LYX_ALIGN_CENTER:
align = "center";
break;
case LYX_ALIGN_RIGHT:
align = "right";
break;
case LYX_ALIGN_BLOCK:
{
if (!multicol && !pwidth.zero())
align = "justified";
break;
}
case LYX_ALIGN_DECIMAL:
{
if (!multicol && !multirow)
align = "decimal";
break;
}
default:
// we should never end up here
break;
}
hAlignCO->setCurrentIndex(hAlignCO->findData(toqstr(align)));
//
QString decimal_point = toqstr(tabular.column_info[col].decimal_point);
if (decimal_point.isEmpty())
decimal_point = toqstr(from_utf8(lyxrc.default_decimal_point));
decimalPointED->setText(decimal_point);
int valign = 0;
switch (tabular.getVAlignment(cell)) {
case Tabular::LYX_VALIGN_TOP:
valign = 0;
break;
case Tabular::LYX_VALIGN_MIDDLE:
valign = 1;
break;
case Tabular::LYX_VALIGN_BOTTOM:
valign = 2;
break;
default:
valign = 0;
break;
}
if (pwidth.zero())
valign = 0;
vAlignCO->setCurrentIndex(valign);
int tableValign = 1;
switch (tabular.tabular_valignment) {
case Tabular::LYX_VALIGN_TOP:
tableValign = 0;
break;
case Tabular::LYX_VALIGN_MIDDLE:
tableValign = 1;
break;
case Tabular::LYX_VALIGN_BOTTOM:
tableValign = 2;
break;
default:
tableValign = 0;
break;
}
TableAlignCO->setCurrentIndex(tableValign);
if (!tabular.is_long_tabular) {
headerStatusCB->setChecked(false);
headerBorderAboveCB->setChecked(false);
headerBorderBelowCB->setChecked(false);
firstheaderStatusCB->setChecked(false);
firstheaderBorderAboveCB->setChecked(false);
firstheaderBorderBelowCB->setChecked(false);
firstheaderNoContentsCB->setChecked(false);
footerStatusCB->setChecked(false);
footerBorderAboveCB->setChecked(false);
footerBorderBelowCB->setChecked(false);
lastfooterStatusCB->setChecked(false);
lastfooterBorderAboveCB->setChecked(false);
lastfooterBorderBelowCB->setChecked(false);
lastfooterNoContentsCB->setChecked(false);
newpageCB->setChecked(false);
captionStatusCB->blockSignals(true);
captionStatusCB->setChecked(false);
captionStatusCB->blockSignals(false);
checkEnabled();
return;
} else {
// longtables cannot have a vertical alignment
TableAlignCO->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE);
}
switch (tabular.longtabular_alignment) {
case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
leftRB->setChecked(true);
break;
case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
centerRB->setChecked(true);
break;
case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
rightRB->setChecked(true);
break;
default:
centerRB->setChecked(true);
break;
}
captionStatusCB->blockSignals(true);
captionStatusCB->setChecked(tabular.ltCaption(row));
captionStatusCB->blockSignals(false);
Tabular::ltType ltt;
bool use_empty;
bool row_set = tabular.getRowOfLTHead(row, ltt);
headerStatusCB->setChecked(row_set);
if (ltt.set) {
headerBorderAboveCB->setChecked(ltt.topDL);
headerBorderBelowCB->setChecked(ltt.bottomDL);
use_empty = true;
} else {
headerBorderAboveCB->setChecked(false);
headerBorderBelowCB->setChecked(false);
firstheaderNoContentsCB->setChecked(false);
use_empty = false;
}
row_set = tabular.getRowOfLTFirstHead(row, ltt);
firstheaderStatusCB->setChecked(row_set);
if (ltt.set && (!ltt.empty || !use_empty)) {
firstheaderBorderAboveCB->setChecked(ltt.topDL);
firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
} else {
firstheaderBorderAboveCB->setChecked(false);
firstheaderBorderBelowCB->setChecked(false);
}
row_set = tabular.getRowOfLTFoot(row, ltt);
footerStatusCB->setChecked(row_set);
if (ltt.set) {
footerBorderAboveCB->setChecked(ltt.topDL);
footerBorderBelowCB->setChecked(ltt.bottomDL);
use_empty = true;
} else {
footerBorderAboveCB->setChecked(false);
footerBorderBelowCB->setChecked(false);
lastfooterNoContentsCB->setChecked(false);
use_empty = false;
}
row_set = tabular.getRowOfLTLastFoot(row, ltt);
lastfooterStatusCB->setChecked(row_set);
if (ltt.set && (!ltt.empty || !use_empty)) {
lastfooterBorderAboveCB->setChecked(ltt.topDL);
lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
} else {
lastfooterBorderAboveCB->setChecked(false);
lastfooterBorderBelowCB->setChecked(false);
}
newpageCB->setChecked(tabular.getLTNewPage(row));
// first header can only be suppressed when there is a header
firstheader_suppressable_ = tabular.haveLTHead()
&& !tabular.haveLTFirstHead();
// last footer can only be suppressed when there is a footer
lastfooter_suppressable_ = tabular.haveLTFoot()
&& !tabular.haveLTLastFoot();
// after setting the features, check if they are enabled
checkEnabled();
}
bool GuiTabular::checkWidgets(bool readonly) const
{
tabularRowED->setReadOnly(readonly);
tabularColumnED->setReadOnly(readonly);
tabularWidthED->setReadOnly(readonly);
specialAlignmentED->setReadOnly(readonly);
columnWidthED->setReadOnly(readonly);
multirowOffsetED->setReadOnly(readonly);
decimalPointED->setReadOnly(readonly);
if (readonly) {
multicolumnCB->setEnabled(false);
multirowCB->setEnabled(false);
rotateCellCB->setEnabled(false);
rotateCellAngleSB->setEnabled(false);
rotateTabularCB->setEnabled(false);
rotateTabularAngleSB->setEnabled(false);
longTabularCB->setEnabled(false);
borders->setEnabled(false);
tabularWidthUnitLC->setEnabled(false);
columnWidthUnitLC->setEnabled(false);
multirowOffsetUnitLC->setEnabled(false);
setBordersGB->setEnabled(false);
allBordersGB->setEnabled(false);
borderStyleGB->setEnabled(false);
booktabsRB->setEnabled(false);
topspaceCO->setEnabled(false);
topspaceUnitLC->setEnabled(false);
bottomspaceCO->setEnabled(false);
bottomspaceUnitLC->setEnabled(false);
interlinespaceCO->setEnabled(false);
interlinespaceUnitLC->setEnabled(false);
hAlignCO->setEnabled(false);
vAlignCO->setEnabled(false);
TableAlignCO->setEnabled(false);
longtableGB->setEnabled(false);
alignmentGB->setEnabled(false);
} else
enableWidgets();
return InsetParamsWidget::checkWidgets();
}
bool GuiTabular::funcEnabled(Tabular::Feature f) const
{
FuncRequest r(LFUN_INSET_MODIFY, "tabular for-dialog" + featureAsString(f));
return getStatus(r).enabled();
}
} // namespace frontend
} // namespace lyx
#include "moc_GuiTabular.cpp"