]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiBox.cpp
On Linux show in crash message box the backtrace
[lyx.git] / src / frontends / qt4 / GuiBox.cpp
index bd3321e20057cb5ff857222b79efcfd4b197701f..d3bd8e86c06320a6b4dc7db3698f0fd05071db68 100644 (file)
@@ -14,7 +14,6 @@
 
 #include "GuiBox.h"
 
-#include "FuncRequest.h"
 #include "LengthCombo.h"
 #include "Length.h"
 #include "qt_helpers.h"
@@ -73,16 +72,15 @@ static QStringList boxGuiSpecialLengthNames()
 }
 
 
-GuiBox::GuiBox(GuiView & lv)
-       : InsetDialog(lv, BOX_CODE, LFUN_BOX_INSERT, "box", "Box Settings")
+GuiBox::GuiBox(QWidget * parent) : InsetParamsWidget(parent)
 {
        setupUi(this);
 
        // fill the box type choice
        ids_ = boxGuiIds();
        gui_names_ = boxGuiNames();
-       foreach (QString const & str, gui_names_)
-               typeCO->addItem(str);
+       for (int i = 0; i != ids_.size(); ++i)
+               typeCO->addItem(gui_names_[i], ids_[i]);
 
        // add the special units to the height choice
        // width needs different handling
@@ -91,97 +89,148 @@ GuiBox::GuiBox(GuiView & lv)
        for (int i = 0; i != ids_spec_.size(); ++i)
                heightUnitsLC->addItem(gui_names_spec_[i], ids_spec_[i]);
 
-       connect(widthED, SIGNAL(textChanged(QString)), this, SLOT(applyView()));
+       connect(widthED, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
        connect(widthUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
-               this, SLOT(applyView()));
-       connect(valignCO, SIGNAL(highlighted(QString)), this, SLOT(applyView()));
-       connect(heightED, SIGNAL(textChanged(QString)), this, SLOT(applyView()));
+               this, SIGNAL(changed()));
+       connect(valignCO, SIGNAL(highlighted(QString)), this, SIGNAL(changed()));
+       connect(heightED, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
        connect(heightUnitsLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
-               this, SLOT(applyView()));
-       connect(halignCO, SIGNAL(activated(int)), this, SLOT(applyView()));
-       connect(ialignCO, SIGNAL(activated(int)), this, SLOT(applyView()));
+               this, SIGNAL(changed()));
+       connect(halignCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
+       connect(ialignCO, SIGNAL(activated(int)), this, SIGNAL(changed()));
 
        heightED->setValidator(unsignedLengthValidator(heightED));
        widthED->setValidator(unsignedLengthValidator(widthED));
 
        // initialize the length validator
-       addCheckedWidget(widthED, widthLA);
+       addCheckedWidget(widthED, widthCB);
        addCheckedWidget(heightED, heightCB);
 
        initDialog();
 }
 
 
-void GuiBox::enableView(bool enable)
+void GuiBox::on_innerBoxCO_activated(int /* index */)
 {
-       typeCO->setEnabled(enable);
-       innerBoxCO->setEnabled(enable);
-       valignCO->setEnabled(enable);
-       ialignCO->setEnabled(enable);
-       halignCO->setEnabled(enable);
-       widthED->setEnabled(enable);
-       widthUnitsLC->setEnabled(enable);
-       heightCB->setEnabled(enable);
-       heightED->setEnabled(enable);
-       heightUnitsLC->setEnabled(enable);
-       pagebreakCB->setEnabled(enable);
-}
-
-
-void GuiBox::on_innerBoxCO_activated(QString const & str)
-{
-       bool const ibox = (str != qt_("None"));
+       QString itype =
+               innerBoxCO->itemData(innerBoxCO->currentIndex()).toString();
+       // handle parbox and minipage the same way
+       bool const ibox =
+               (itype != "none"
+                && itype != "makebox");
+       QString const outer =
+               typeCO->itemData(typeCO->currentIndex()).toString();
        valignCO->setEnabled(ibox);
        ialignCO->setEnabled(ibox);
-       halignCO->setEnabled(!ibox);
+       if (heightCB->isChecked() && !ibox)
+               heightCB->setChecked(false);
        heightCB->setEnabled(ibox);
-       pagebreakCB->setEnabled(!ibox && typeCO->currentIndex() == 1);
+       // the width can only be selected for makebox or framebox
+       widthCB->setEnabled(itype == "makebox"
+                           || (outer == "Boxed" && itype == "none"));
+       widthCB->setChecked(!widthED->text().isEmpty());
+       // except for frameless and boxed, the width cannot be specified if
+       // there is no inner box
+       bool const width_enabled =
+               ibox || outer == "Frameless" || outer == "Boxed";
+       // enable if width_enabled, except if checkbaox is active but unset
+       widthED->setEnabled(width_enabled || (widthCB->isEnabled() && widthCB->isChecked()));
+       widthUnitsLC->setEnabled(width_enabled || (widthCB->isEnabled() && widthCB->isChecked()));
+       if (!widthCB->isChecked() && widthCB->isEnabled()) {
+               widthED->setEnabled(false);
+               widthUnitsLC->setEnabled(false);
+       }
+       // halign is only allowed without inner box and if a width is used and if
+       // pagebreak is not used
+       halignCO->setEnabled(!pagebreakCB->isChecked() && widthCB->isChecked()
+                            && ((!ibox && outer == "Boxed") || itype == "makebox"));
+       // pagebreak is only allowed for Boxed without inner box
+       pagebreakCB->setEnabled(!ibox && outer == "Boxed");
        setSpecial(ibox);
-       applyView();
+       changed();
 }
 
 
 void GuiBox::on_typeCO_activated(int index)
 {
-       bool const frameless = (index == 0);
-       if (frameless) {
-               valignCO->setEnabled(true);
-               ialignCO->setEnabled(true);
-               halignCO->setEnabled(false);
-               heightCB->setEnabled(true);
-               setSpecial(true);
+       QString const type =
+               typeCO->itemData(index).toString();
+       bool const frameless = (type == "Frameless");
+       QString itype =
+               innerBoxCO->itemData(innerBoxCO->currentIndex()).toString();
+       setInnerType(frameless, itype);
+       // refresh itype because it might have been changed in setInnerType
+       itype =
+               innerBoxCO->itemData(innerBoxCO->currentIndex()).toString();
+       // handle parbox and minipage the same way
+       bool const ibox =
+               (itype != "none"
+                && itype != "makebox");
+       if (frameless && itype != "makebox") {
+               valignCO->setEnabled(ibox);
+               ialignCO->setEnabled(ibox);
+               if (heightCB->isChecked() && !ibox)
+                       heightCB->setChecked(false);
+               heightCB->setEnabled(ibox);
+               setSpecial(ibox);
        }
-       if (index != 1)
+       // the width can only be selected for makebox or framebox
+       widthCB->setEnabled(itype == "makebox"
+                           || (type == "Boxed" && itype == "none"));
+       widthCB->setChecked(itype != "none" && !widthCB->isEnabled());
+       // except for frameless and boxed, the width cannot be specified if
+       // there is no inner box
+       bool const width_enabled =
+               itype != "none" || frameless || type == "Boxed";
+       // enable if width_enabled, except if checkbaox is active but unset
+       widthED->setEnabled(width_enabled || (widthCB->isEnabled() && widthCB->isChecked()));
+       widthUnitsLC->setEnabled(width_enabled || (widthCB->isEnabled() && widthCB->isChecked()));
+       if (!widthCB->isChecked() && widthCB->isEnabled()) {
+               widthED->setEnabled(false);
+               widthUnitsLC->setEnabled(false);
+       }
+       // halign is only allowed without inner box and if a width is used and if
+       // pagebreak is not used
+       halignCO->setEnabled(!pagebreakCB->isChecked() && widthCB->isChecked()
+                            && ((itype == "none" && type == "Boxed") || itype == "makebox"));
+       // pagebreak is only allowed for Boxed without inner box
+       pagebreakCB->setEnabled(type == "Boxed" && itype == "none");
+       if (type != "Boxed")
                pagebreakCB->setChecked(false);
-       int itype = innerBoxCO->currentIndex();
-       if (innerBoxCO->count() == 2)
-               ++itype;
-       pagebreakCB->setEnabled(index == 1 && itype == 0);
-       widthED->setEnabled(index != 5);
-       widthUnitsLC->setEnabled(index != 5);
-       setInnerType(frameless, itype);
-       applyView();
+       changed();
 }
 
 
 void GuiBox::initDialog()
 {
-       setInnerType(true, 2);
+       setInnerType(true, toqstr("minipage"));
        widthED->setText("100");
+       widthCB->setChecked(true);
+       widthCB->setEnabled(false);
        widthUnitsLC->setCurrentItem(Length::PCW);
-       heightCB->setCheckState(Qt::Checked);
        heightED->setText("1");
        heightUnitsLC->setCurrentItem("totalheight");
 }
 
 
+void GuiBox::on_widthCB_stateChanged(int)
+{
+       if (widthCB->isEnabled()) {
+               widthED->setEnabled(widthCB->isChecked());
+               widthUnitsLC->setEnabled(widthCB->isChecked());
+               halignCO->setEnabled(widthCB->isChecked());
+       }
+       changed();
+}
+
+
 void GuiBox::on_heightCB_stateChanged(int state)
 {
        bool const enable = (innerBoxCO->currentText() != qt_("None"))
                && (state == Qt::Checked);
        heightED->setEnabled(enable);
        heightUnitsLC->setEnabled(enable);
-       applyView();
+       changed();
 }
 
 
@@ -189,6 +238,9 @@ void GuiBox::on_pagebreakCB_stateChanged()
 {
        bool pbreak = (pagebreakCB->checkState() == Qt::Checked);
        innerBoxCO->setEnabled(!pbreak);
+       widthCB->setEnabled(!pbreak);
+       if (pbreak)
+               widthCB->setChecked(!pbreak);
        widthED->setEnabled(!pbreak);
        widthUnitsLC->setEnabled(!pbreak);
        if (!pbreak) {
@@ -202,7 +254,7 @@ void GuiBox::on_pagebreakCB_stateChanged()
        heightED->setEnabled(false);
        heightUnitsLC->setEnabled(false);
        setSpecial(false);
-       applyView();
+       changed();
 }
 
 
@@ -218,22 +270,17 @@ void GuiBox::paramsToDialog(Inset const * inset)
                pagebreakCB->setChecked(false);
        }
 
-       pagebreakCB->setEnabled(type == "Boxed" && !params.inner_box);
-
-       for (int i = 0; i != gui_names_.size(); ++i) {
-               if (type == ids_[i])
-                       typeCO->setCurrentIndex(i);
-       }
+       typeCO->setCurrentIndex(typeCO->findData(type));
 
        // default: minipage
-       int inner_type = 2;
+       QString inner_type = "minipage";
        if (!params.inner_box)
-               // none
-               inner_type = 0;
+               inner_type = "none";
        if (params.use_parbox)
-               // parbox
-               inner_type = 1;
-       bool frameless = (params.type == "Frameless");
+               inner_type = "parbox";
+       if (params.use_makebox)
+               inner_type = "makebox";
+       bool const frameless = (params.type == "Frameless");
        setInnerType(frameless, inner_type);
 
        char c = params.pos;
@@ -243,24 +290,43 @@ void GuiBox::paramsToDialog(Inset const * inset)
        c = params.hor_pos;
        halignCO->setCurrentIndex(string("lcrs").find(c, 0));
 
-       bool ibox = params.inner_box;
+       bool ibox = (params.inner_box && !params.use_makebox);
        valignCO->setEnabled(ibox);
        ialignCO->setEnabled(ibox);
-       halignCO->setEnabled(!ibox);
        setSpecial(ibox);
 
+       // halign is only allowed without inner box and if a width is used and if
+       // pagebreak is not used
+       halignCO->setEnabled(!pagebreakCB->isChecked() && widthCB->isChecked()
+                            && ((!ibox && type == "Boxed") || params.use_makebox));
+       // pagebreak is only allowed for Boxed without inner box
+       pagebreakCB->setEnabled(!ibox && type == "Boxed");
+
        Length::UNIT const default_unit = Length::defaultUnit();
 
-       lengthToWidgets(widthED, widthUnitsLC,
-               (params.width).asString(), default_unit);
+       // the width can only be selected for makebox or framebox
+       widthCB->setEnabled(inner_type == "makebox"
+                           || (type == "Boxed"
+                               && !ibox && !pagebreakCB->isChecked()));
+       if (params.width.empty()) {
+               widthCB->setChecked(false);
+               lengthToWidgets(widthED, widthUnitsLC,
+                       params.width, default_unit);
+       } else {
+               widthCB->setChecked(true);
+               lengthToWidgets(widthED, widthUnitsLC,
+                       params.width, default_unit);
+               QString const special = toqstr(params.special);
+               if (!special.isEmpty() && special != "none")
+                       widthUnitsLC->setCurrentItem(special);
+       }
 
-       QString const special = toqstr(params.special);
-       if (!special.isEmpty() && special != "none")
-               widthUnitsLC->setCurrentItem(special);
+       widthED->setEnabled(widthCB->isChecked());
+       widthUnitsLC->setEnabled(widthCB->isChecked());
 
        lengthToWidgets(heightED, heightUnitsLC,
                (params.height).asString(), default_unit);
-       
+
        QString const height_special = toqstr(params.height_special);
        if (!height_special.isEmpty() && height_special != "none")
                heightUnitsLC->setCurrentItem(height_special);
@@ -285,13 +351,16 @@ docstring GuiBox::dialogToParams() const
        if (pagebreak)
                box_type = "Framed";
        else
-               box_type = fromqstr(ids_[typeCO->currentIndex()]);
+               box_type = fromqstr(typeCO->itemData(
+                               typeCO->currentIndex()).toString());
 
        InsetBoxParams params(box_type);
        params.inner_box =
                (!pagebreak && innerBoxCO->currentText() != qt_("None"));
        params.use_parbox =
                (!pagebreak && innerBoxCO->currentText() == qt_("Parbox"));
+       params.use_makebox =
+               (!pagebreak && innerBoxCO->currentText() == qt_("Makebox"));
 
        params.pos = "tcb"[valignCO->currentIndex()];
        params.inner_pos = "tcbs"[ialignCO->currentIndex()];
@@ -300,13 +369,22 @@ docstring GuiBox::dialogToParams() const
        QString unit =
                widthUnitsLC->itemData(widthUnitsLC->currentIndex()).toString();
        QString value = widthED->text();
-       if (ids_spec_.contains(unit) && !isValidLength(fromqstr(value))) {
-               params.special = fromqstr(unit);
-               // Note: the unit is simply ignored in this case
-               params.width = Length(value.toDouble(), Length::IN);
+
+       if (widthED->isEnabled()) {
+               if (ids_spec_.contains(unit) && !isValidLength(fromqstr(value))) {
+                       params.special = fromqstr(unit);
+                       // Note: the unit is simply ignored in this case
+                       params.width = Length(value.toDouble(), Length::IN);
+               } else {
+                       params.special = "none";
+                       // we must specify a valid length in this case
+                       if (value.isEmpty())
+                               widthED->setText("0");
+                       params.width = Length(widgetsToLength(widthED, widthUnitsLC));
+               }
        } else {
                params.special = "none";
-               params.width = Length(widgetsToLength(widthED, widthUnitsLC));
+               params.width = Length();
        }
 
        // the height parameter is omitted if the value
@@ -357,31 +435,23 @@ void GuiBox::setSpecial(bool ibox)
 }
 
 
-void GuiBox::setInnerType(bool frameless, int i)
+void GuiBox::setInnerType(bool frameless, QString const & type)
 {
-       // with "frameless" boxes, inner box is mandatory (i.e. is the actual box)
+       // with "frameless" boxes, inner box is mandatory
+       // (i.e. is the actual box)
        // we have to remove "none" then and adjust the combo
-       if (frameless) {
-               innerBoxCO->clear();
-               innerBoxCO->addItem(qt_("Parbox"));
-               innerBoxCO->addItem(qt_("Minipage"));
-               if (i != 0)
-                       innerBoxCO->setCurrentIndex(i - 1);
-               else
-                       innerBoxCO->setCurrentIndex(i);
-       } else {
-               innerBoxCO->clear();
-               innerBoxCO->addItem(qt_("None"));
-               innerBoxCO->addItem(qt_("Parbox"));
-               innerBoxCO->addItem(qt_("Minipage"));
-               innerBoxCO->setCurrentIndex(i);
-       }
+       innerBoxCO->clear();
+       if (!frameless)
+               innerBoxCO->addItem(qt_("None"), toqstr("none"));
+       else
+               innerBoxCO->addItem(qt_("Makebox"), toqstr("makebox"));
+       innerBoxCO->addItem(qt_("Parbox"), toqstr("parbox"));
+       innerBoxCO->addItem(qt_("Minipage"), toqstr("minipage"));
+       int i = (innerBoxCO->findData(type) != -1)
+               ? innerBoxCO->findData(type) : 0;
+       innerBoxCO->setCurrentIndex(i);
 }
 
-
-Dialog * createGuiBox(GuiView & lv) { return new GuiBox(lv); }
-
-
 } // namespace frontend
 } // namespace lyx