]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt2/QParagraph.C
better selection and scrolling behaviour
[lyx.git] / src / frontends / qt2 / QParagraph.C
index d31983a8827e4fe895a0095d3033bfecbf7294b0..eec863856ff5deafdd5ae4d5412bf7101c5c7c23 100644 (file)
 /**
  * \file QParagraph.C
- * Copyright 2001 LyX Team
- * see the file COPYING
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
  *
- * \author John Levon, moz@compsoc.man.ac.uk
+ * \author Edwin Leuven
+ *
+ * Full author contact details are available in file CREDITS
  */
 
 #include <config.h>
 
-#include "QParagraphDialog.h"
+#ifdef __GNUG__
+#pragma implementation
+#endif
 
+#include "ControlParagraph.h"
 #include "QParagraph.h"
-#include "Dialogs.h"
-#include "Liason.h"
-#include "gettext.h"
-#include "buffer.h"
-#include "QtLyXView.h"
-#include "lyxtext.h"
-#include "debug.h"
-#include "BufferView.h"
+#include "QParagraphDialog.h"
+#include "Qt2BC.h"
 #include "ParagraphParameters.h"
+#include "lyxrc.h" // to set the deafult length values
+#include "gettext.h"
+#include "layout.h" // LyXAlignment
+#include "helper_funcs.h"
+#include "lyxgluelength.h"
+#include "vspace.h"
 
-using SigC::slot;
-using Liason::setMinibuffer;
-using std::endl;
+#include "support/lstrings.h"
+#include "support/LAssert.h"
 
+#include <qcombobox.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qbuttongroup.h>
 
-QParagraph::QParagraph(LyXView *v, Dialogs *d)
-       : dialog_(0), lv_(v), d_(d), h_(0)
-{
-       d->showParagraph.connect(slot(this, &QParagraph::show));
-}
+#include <functional>
 
+using std::vector;
+using std::bind2nd;
+using std::remove_if;
+
+typedef Qt2CB<ControlParagraph, Qt2DB<QParagraphDialog> > base_class;
 
-QParagraph::~QParagraph()
-{
-       delete dialog_;
-}
 
+QParagraph::QParagraph()
+       : base_class(_("Paragraph Layout"))
+{}
 
-void QParagraph::update(bool switched)
+
+void QParagraph::build_dialog()
 {
-       if (switched) {
-               hide();
-               return;
+       // the tabbed folder
+       dialog_.reset(new QParagraphDialog(this));
+
+       // Create the contents of the unit choices
+       // Don't include the "%" terms...
+       units_ = getLatexUnits();
+       vector<string>::iterator del =
+               remove_if(units_.begin(), units_.end(),
+                         bind2nd(contains_functor(), "%"));
+       units_.erase(del, units_.end());
+
+       for (vector<string>::const_iterator it = units_.begin();
+               it != units_.end(); ++it) {
+               dialog_->unitAbove->insertItem(it->c_str());
+               dialog_->unitBelow->insertItem(it->c_str());
        }
 
-       if (!lv_->view()->available())
-               return;
+       // Manage the ok, apply, restore and cancel/close buttons
+       bc().setOK(dialog_->okPB);
+       bc().setApply(dialog_->applyPB);
+       bc().setCancel(dialog_->closePB);
+       bc().setRestore(dialog_->restorePB);
+       bc().addReadOnly(dialog_->paragraphTab);
+}
 
-       Buffer * buf = lv_->view()->buffer();
 
-       if (readonly!=buf->isReadonly()) {
-               readonly = buf->isReadonly();
-               dialog_->setReadOnly(readonly);
-       }
+namespace {
 
-       LyXText * text(lv_->view()->getLyXText());
-       Paragraph * par = text->cursor.par();
-
-       int align = par->getAlign();
-
-       if (align==LYX_ALIGN_LAYOUT)
-               align = textclasslist.Style(buf->params.textclass, par->getLayout()).align;
-
-       ParagraphParameters * params = &(par->params());
-
-       if (params->spaceTop().kind() == VSpace::LENGTH) {
-               LyXGlueLength above = params->spaceTop().length();
-               lyxerr[Debug::GUI] << "Reading above space : \"" << params->spaceTop().length().asString() << "\"" << endl;
-               dialog_->setAboveLength(above.len().value(), above.plus().value(), above.minus().value(),
-                       above.len().unit(), above.plus().unit(), above.minus().unit());
-       } else
-               dialog_->setAboveLength(0.0, 0.0, 0.0, LyXLength::UNIT_NONE, LyXLength::UNIT_NONE, LyXLength::UNIT_NONE);
-
-       if (params->spaceBottom().kind() == VSpace::LENGTH) {
-               LyXGlueLength below = params->spaceBottom().length();
-               lyxerr[Debug::GUI] << "Reading below space : \"" << params->spaceBottom().length().asString() << "\"" << endl;
-               dialog_->setBelowLength(below.len().value(), below.plus().value(), below.minus().value(),
-                       below.len().unit(), below.plus().unit(), below.minus().unit());
-       } else
-               dialog_->setBelowLength(0.0, 0.0, 0.0, LyXLength::UNIT_NONE, LyXLength::UNIT_NONE, LyXLength::UNIT_NONE);
-
-       dialog_->setLabelWidth(text->cursor.par()->getLabelWidthString().c_str());
-       dialog_->setAlign(align);
-       dialog_->setChecks(params->lineTop(), params->lineBottom(),
-               params->pagebreakTop(), params->pagebreakBottom(), params->noindent());
-       dialog_->setSpace(params->spaceTop().kind(), params->spaceBottom().kind(),
-               params->spaceTop().keep(), params->spaceBottom().keep());
-
-       // now the extras page
-
-       LyXLength extrawidth;
-       float val = 0.0;
-       LyXLength::UNIT unit = LyXLength::CM;
-       params = &(par->params());
-       if (isValidLength(params->pextraWidth(), &extrawidth)) {
-               lyxerr[Debug::GUI] << "Reading extra width \"" << extrawidth.asString() << "\"" << endl;
-               val = extrawidth.value();
-               unit = extrawidth.unit();
+VSpace setVSpaceFromWidgets(int spacing,
+                           string value,
+                           string unit,
+                           bool keep)
+{
+       VSpace space;
+
+       switch (spacing) {
+       case 0:
+               space = VSpace(VSpace::NONE);
+               break;
+       case 1:
+               space = VSpace(VSpace::DEFSKIP);
+               break;
+       case 2:
+               space = VSpace(VSpace::SMALLSKIP);
+               break;
+       case 3:
+               space = VSpace(VSpace::MEDSKIP);
+               break;
+       case 4:
+               space = VSpace(VSpace::BIGSKIP);
+               break;
+       case 5:
+               space = VSpace(VSpace::VFILL);
+               break;
+       case 6:
+               string s;
+               string const length = trim(value);
+               if (isValidGlueLength(length)) {
+                       s = length;
+               } else if (!length.empty()){
+                       string u = trim(unit);
+                       u = subst(u, "%%", "%");
+                       s = length + u;
+               }
+               space = VSpace(LyXGlueLength(s));
+               break;
        }
 
-       lyxerr[Debug::GUI] << "Reading widthp \"" << params->pextraWidthp() << "\"" << endl;
+       space.setKeep(keep);
 
-       dialog_->setExtra(val, unit, params->pextraWidthp(),
-               params->pextraAlignment(),
-               params->pextraHfill(),
-               params->pextraStartMinipage(),
-               static_cast<Paragraph::PEXTRA_TYPE>(params->pextraType()));
+       return space;
 }
 
+} // namespace anon
+
 
 void QParagraph::apply()
 {
-       if (readonly)
-               return;
-
-       VSpace spaceabove;
-       VSpace spacebelow;
-
-       if (dialog_->getSpaceAboveKind()==VSpace::LENGTH)
-               spaceabove = VSpace(dialog_->getAboveLength());
-       else
-               spaceabove = VSpace(dialog_->getSpaceAboveKind());
-
-       if (dialog_->getSpaceBelowKind()==VSpace::LENGTH)
-               spacebelow = VSpace(dialog_->getBelowLength());
-       else
-               spacebelow = VSpace(dialog_->getSpaceBelowKind());
-
-       spaceabove.setKeep(dialog_->getAboveKeep());
-       spacebelow.setKeep(dialog_->getBelowKeep());
-
-       lyxerr[Debug::GUI] << "Setting above space \"" << LyXGlueLength(spaceabove.length().asString()).asString() << "\"" << endl;
-       lyxerr[Debug::GUI] << "Setting below space \"" << LyXGlueLength(spacebelow.length().asString()).asString() << "\"" << endl;
-
-       LyXText * text(lv_->view()->getLyXText());
-       text->setParagraph(lv_->view(),
-                          dialog_->getLineAbove(), dialog_->getLineBelow(),
-                          dialog_->getPagebreakAbove(), dialog_->getPagebreakBelow(),
-                          spaceabove, spacebelow, Spacing(), dialog_->getAlign(),
-                          dialog_->getLabelWidth(), dialog_->getNoIndent());
-
-       // extra stuff
-
-       string width("");
-       string widthp("");
-
-       LyXLength extrawidth(dialog_->getExtraWidth());
-       if (extrawidth.unit()==LyXLength::UNIT_NONE) {
-               widthp = dialog_->getExtraWidthPercent();
-       } else
-               width = extrawidth.asString();
+       ParagraphParameters & params = controller().params();
+
+       // SPACING ABOVE
+       // If a vspace kind is "Length" but there's no text in
+       // the input field, reset the kind to "None".
+       if (dialog_->spacingAbove->currentItem() == 5
+           && dialog_->valueAbove->text().isEmpty())
+               dialog_->spacingAbove->setCurrentItem(0);
+
+       VSpace const space_top =
+               setVSpaceFromWidgets(dialog_->spacingAbove->currentItem(),
+                                    dialog_->valueAbove->text().latin1(),
+                                    dialog_->unitAbove->currentText().latin1(),
+                                    dialog_->keepAbove->isChecked());
+
+       params.spaceTop(space_top);
+
+       // SPACING BELOW
+       if (dialog_->spacingBelow->currentItem() == 5
+           && dialog_->valueBelow->text().isEmpty())
+               dialog_->spacingBelow->setCurrentItem(0);
+
+       VSpace const space_bottom =
+       setVSpaceFromWidgets(dialog_->spacingBelow->currentItem(),
+                            dialog_->valueBelow->text().latin1(),
+                            dialog_->unitBelow->currentText().latin1(),
+                            dialog_->keepBelow->isChecked());
+
+       params.spaceBottom(space_bottom);
+
+       // alignment
+       LyXAlignment align;
+       switch (dialog_->align->currentItem()) {
+       case 0:
+               align = LYX_ALIGN_BLOCK;
+               break;
+       case 1:
+               align = LYX_ALIGN_LEFT;
+               break;
+       case 2:
+               align = LYX_ALIGN_RIGHT;
+               break;
+       case 3:
+               align = LYX_ALIGN_CENTER;
+               break;
+       default:
+               align = LYX_ALIGN_BLOCK;
+       }
+       params.align(align);
+
+       // get spacing
+       Spacing::Space linespacing = Spacing::Default;
+       string other;
+       switch (dialog_->linespacing->currentItem()) {
+       case 0:
+               linespacing = Spacing::Default;
+               break;
+       case 1:
+               linespacing = Spacing::Single;
+               break;
+       case 2:
+               linespacing = Spacing::Onehalf;
+               break;
+       case 3:
+               linespacing = Spacing::Double;
+               break;
+       case 4:
+               linespacing = Spacing::Other;
+               other = dialog_->linespacingValue->text().latin1();
+               break;
+       }
 
-       lyxerr[Debug::GUI] << "Setting extrawidth \"" << width << "\"" << endl;
-       lyxerr[Debug::GUI] << "Setting percent extrawidth \"" << widthp << "\"" << endl;
+       Spacing const spacing(linespacing, other);
+       params.spacing(spacing);
 
-       lv_->view()->update(text,
-                           BufferView::SELECT |
-                           BufferView::FITCUR |
-                           BufferView::CHANGE);
+       // lines and pagebreaks
+       params.lineTop(dialog_->lineAbove->isChecked());
+       params.lineBottom(dialog_->lineBelow->isChecked());
+       params.pagebreakTop(dialog_->pagebreakAbove->isChecked());
+       params.pagebreakBottom(dialog_->pagebreakBelow->isChecked());
+       // label width
+       params.labelWidthString(dialog_->labelWidth->text().latin1());
+       // indendation
+       params.noindent(dialog_->noindent->isChecked());
 
-       lv_->buffer()->markDirty();
-       setMinibuffer(lv_, _("Paragraph layout set"));
 }
 
 
-void QParagraph::show()
-{
-       if (!dialog_)
-               dialog_ = new QParagraphDialog(this, 0,
-                                              _("LyX: Paragraph Settings"),
-                                              false);
-
-       if (!dialog_->isVisible())
-               h_ = d_->hideBufferDependent
-                       .connect(slot(this, &QParagraph::hide));
-
-       dialog_->raise();
-       dialog_->setActiveWindow();
-       update();
+namespace {
 
-       dialog_->show();
-}
-
-
-void QParagraph::close()
+void setWidgetsFromVSpace(VSpace const & space,
+                         QComboBox * spacing,
+                         QLineEdit * value,
+                         QComboBox * unit,
+                         QCheckBox * keep, vector<string> units_)
 {
-       h_.disconnect();
+       value->setText("");
+       value->setEnabled(false);
+       unit->setEnabled(false);
+
+       int item = 0;
+       switch (space.kind()) {
+       case VSpace::NONE:
+               item = 0;
+               break;
+       case VSpace::DEFSKIP:
+               item = 1;
+               break;
+       case VSpace::SMALLSKIP:
+               item = 2;
+               break;
+       case VSpace::MEDSKIP:
+               item = 3;
+               break;
+       case VSpace::BIGSKIP:
+               item = 4;
+               break;
+       case VSpace::VFILL:
+               item = 5;
+               break;
+       case VSpace::LENGTH:
+               item = 6;
+               value->setEnabled(true);
+               unit->setEnabled(true);
+               string length = space.length().asString();
+               string const default_unit =
+                       (lyxrc.default_papersize > 3) ? "cm" : "in";
+               string supplied_unit = default_unit;
+               LyXLength len(length);
+               if ((isValidLength(length)
+                    || isStrDbl(length)) && !len.zero()) {
+                       ostringstream buffer;
+                       buffer << len.value();
+                       length = buffer.str();
+                       supplied_unit = subst(stringFromUnit(len.unit()),
+                                             "%", "%%");
+               }
+
+               int unit_item = 0;
+               int i = 0;
+               for (vector<string>::const_iterator it = units_.begin();
+                    it != units_.end(); ++it) {
+                       if (*it == default_unit) {
+                               unit_item = i;
+                       }
+                       if (*it == supplied_unit) {
+                               unit_item = i;
+                               break;
+                       }
+                       i += 1;
+               }
+               value->setText(length.c_str());
+               unit->setCurrentItem(unit_item);
+               break;
+       }
+       spacing->setCurrentItem(item);
+       keep->setChecked(space.keep());
 }
 
+} // namespace anon
+
 
-void QParagraph::hide()
+void QParagraph::update_contents()
 {
-       dialog_->hide();
-       close();
+       ParagraphParameters const & params = controller().params();
+
+       // label width
+       string const & labelwidth = params.labelWidthString();
+       dialog_->labelWidth->setText(labelwidth.c_str());
+       dialog_->labelwidthGB->setEnabled(
+               labelwidth != _("Senseless with this layout!"));
+
+       // alignment
+       int i;
+       switch (params.align()) {
+       case LYX_ALIGN_LEFT:
+               i = 1;
+               break;
+       case LYX_ALIGN_RIGHT:
+               i = 2;
+               break;
+       case LYX_ALIGN_CENTER:
+               i = 3;
+               break;
+       default:
+               i = 0;
+               break;
+       }
+       dialog_->align->setCurrentItem(i);
+
+
+       //LyXAlignment alignpos = controller().alignPossible();
+
+       // no inset-text-owned paragraph may have pagebreaks
+       bool ininset = controller().inInset();
+       dialog_->pagebreakAbove->setEnabled(!ininset);
+       dialog_->pagebreakBelow->setEnabled(!ininset);
+
+       // lines, pagebreaks and indent
+       dialog_->lineAbove->setChecked(params.lineTop());
+       dialog_->lineBelow->setChecked(params.lineBottom());
+       dialog_->pagebreakAbove->setChecked(params.pagebreakTop());
+       dialog_->pagebreakBelow->setChecked(params.pagebreakBottom());
+       dialog_->noindent->setChecked(params.noindent());
+
+       // linespacing
+       int linespacing;
+       Spacing const & space = params.spacing();
+       switch (space.getSpace()) {
+       case Spacing::Single:
+               linespacing = 1;
+               break;
+       case Spacing::Onehalf:
+               linespacing = 2;
+               break;
+       case Spacing::Double:
+               linespacing = 3;
+               break;
+       case Spacing::Other:
+               linespacing = 4;
+               break;
+       default:
+               linespacing = 0;
+               break;
+       }
+       dialog_->linespacing->setCurrentItem(linespacing);
+       if (space.getSpace() == Spacing::Other) {
+               string const sp = tostr(space.getValue());
+               dialog_->linespacingValue->setText(sp.c_str());
+               dialog_->linespacingValue->setEnabled(true);
+       } else {
+               dialog_->linespacingValue->setText("");
+               dialog_->linespacingValue->setEnabled(false);
+       }
+
+       // vspace top
+       setWidgetsFromVSpace(params.spaceTop(),
+                            dialog_->spacingAbove,
+                            dialog_->valueAbove,
+                            dialog_->unitAbove,
+                            dialog_->keepAbove,units_);
+
+       // vspace bottom
+       setWidgetsFromVSpace(params.spaceBottom(),
+                            dialog_->spacingBelow,
+                            dialog_->valueBelow,
+                            dialog_->unitBelow,
+                            dialog_->keepBelow,units_);
+
+       // no indent
+       dialog_->noindent->setChecked(params.noindent());
 }