diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index c66771b4ef..95db684d2b 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -49,6 +49,7 @@ #include "ParagraphParameters.h" #include "pariterator.h" #include "rowpainter.h" +#include "toc.h" #include "undo.h" #include "vspace.h" @@ -1033,6 +1034,11 @@ FuncStatus BufferView::Pimpl::getStatus(FuncRequest const & cmd) case LFUN_FONT_STATE: case LFUN_INSERT_LABEL: case LFUN_GOTO_PARAGRAPH: + // FIXME handle non-trivially + case LFUN_OUTLINE_UP: + case LFUN_OUTLINE_DOWN: + case LFUN_OUTLINE_IN: + case LFUN_OUTLINE_OUT: case LFUN_GOTONOTE: case LFUN_REFERENCE_GOTO: case LFUN_WORD_FIND: @@ -1194,6 +1200,25 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd) break; } + case LFUN_OUTLINE_UP: + lyx::toc::outline(lyx::toc::Up, cursor_); + cursor_.text()->setCursor(cursor_, cursor_.pit(), 0); + updateCounters(*buffer_); + break; + case LFUN_OUTLINE_DOWN: + lyx::toc::outline(lyx::toc::Down, cursor_); + cursor_.text()->setCursor(cursor_, cursor_.pit(), 0); + updateCounters(*buffer_); + break; + case LFUN_OUTLINE_IN: + lyx::toc::outline(lyx::toc::In, cursor_); + updateCounters(*buffer_); + break; + case LFUN_OUTLINE_OUT: + lyx::toc::outline(lyx::toc::Out, cursor_); + updateCounters(*buffer_); + break; + case LFUN_GOTONOTE: bv_funcs::gotoInset(bv_, InsetBase::NOTE_CODE, false); break; diff --git a/src/LyXAction.C b/src/LyXAction.C index 4617afdd76..de8d1ff455 100644 --- a/src/LyXAction.C +++ b/src/LyXAction.C @@ -241,6 +241,10 @@ void LyXAction::init() { LFUN_DOWN_PARAGRAPH, "paragraph-down", ReadOnly | NoUpdate}, { LFUN_DOWN_PARAGRAPHSEL, "paragraph-down-select", ReadOnly }, { LFUN_GOTO_PARAGRAPH, "paragraph-goto", ReadOnly }, + { LFUN_OUTLINE_UP, "outline-up", Noop }, + { LFUN_OUTLINE_DOWN, "outline-down", Noop }, + { LFUN_OUTLINE_IN, "outline-in", Noop }, + { LFUN_OUTLINE_OUT, "outline-out", Noop }, { LFUN_PARAGRAPH_SPACING, "paragraph-spacing", Noop }, { LFUN_UP_PARAGRAPH, "paragraph-up", ReadOnly | NoUpdate}, { LFUN_UP_PARAGRAPHSEL, "paragraph-up-select", ReadOnly }, diff --git a/src/frontends/controllers/ControlToc.C b/src/frontends/controllers/ControlToc.C index f64cb4ad62..1b8f88a8a7 100644 --- a/src/frontends/controllers/ControlToc.C +++ b/src/frontends/controllers/ControlToc.C @@ -8,9 +8,12 @@ * Full author contact details are available in file CREDITS. */ +#include + #include #include "ControlToc.h" +#include "funcrequest.h" #include "gettext.h" using std::vector; @@ -34,6 +37,31 @@ void ControlToc::goTo(toc::TocItem const & item) } +bool ControlToc::canOutline(string const & type) +{ + return type == "TOC"; +} + + +void ControlToc::outline(toc::OutlineOp op) +{ + switch (op) { + case toc::Up: + kernel().dispatch(FuncRequest(LFUN_OUTLINE_UP)); + break; + case toc::Down: + kernel().dispatch(FuncRequest(LFUN_OUTLINE_DOWN)); + break; + case toc::In: + kernel().dispatch(FuncRequest(LFUN_OUTLINE_IN)); + break; + case toc::Out: + kernel().dispatch(FuncRequest(LFUN_OUTLINE_OUT)); + break; + } +} + + vector const ControlToc::getTypes() const { return toc::getTypes(kernel().buffer()); diff --git a/src/frontends/controllers/ControlToc.h b/src/frontends/controllers/ControlToc.h index f71751c2fe..4cbf8b6368 100644 --- a/src/frontends/controllers/ControlToc.h +++ b/src/frontends/controllers/ControlToc.h @@ -38,6 +38,12 @@ public: /// Given a type, returns the contents toc::Toc const getContents(std::string const & type) const; + + /// Apply the selected outlining operation + void outline(toc::OutlineOp op); + + /// Test if outlining operation is possible + bool canOutline(std::string const & type); }; } // namespace frontend diff --git a/src/frontends/qt2/QToc.C b/src/frontends/qt2/QToc.C index b3c5f79827..ded6e6f835 100644 --- a/src/frontends/qt2/QToc.C +++ b/src/frontends/qt2/QToc.C @@ -48,6 +48,8 @@ void QToc::build_dialog() // Manage the cancel/close button bcview().setCancel(dialog_->closePB); + type_ = toc::getType(controller().params().getCmdName()); + dialog_->enableButtons(); } @@ -67,6 +69,8 @@ void QToc::updateType() setTitle(guiname); } } + type_ = type; + dialog_->enableButtons(); } @@ -83,6 +87,8 @@ void QToc::updateToc(int newdepth) string type; if (!choice.empty()) type = choice[dialog_->typeCO->currentItem()]; + type_ = type; + dialog_->enableButtons(); toc::Toc const & contents = controller().getContents(type); @@ -107,7 +113,9 @@ void QToc::updateToc(int newdepth) QListViewItem * last = 0; QListViewItem * parent = 0; QListViewItem * item; - + QListViewItem * selected_item = 0; + bool multiple = false; + // Yes, it is this ugly. Two reasons - root items must have // a QListView parent, rather than QListViewItem; and the // TOC can move in and out an arbitrary number of levels @@ -157,14 +165,34 @@ void QToc::updateToc(int newdepth) item->setOpen(iter->depth < depth_); curdepth = iter->depth; last = item; + + // Recognise part past the counter + if (iter->str.substr(iter->str.find(' ') + 1) == text_) { + if (selected_item == 0) + selected_item = item; + else + // more than one match + multiple = true; + } } dialog_->tocLV->setUpdatesEnabled(true); dialog_->tocLV->update(); + if (!multiple) { + dialog_->tocLV->scrollBy(0, selected_item->itemPos() + - dialog_->tocLV->height() / 2); + dialog_->tocLV->setSelected(selected_item, true); + } setTitle(fromqstr(dialog_->typeCO->currentText())); } +bool QToc::canOutline() +{ + return controller().canOutline(type_); +} + + void QToc::select(string const & text) { toc::Toc::const_iterator iter = toclist.begin(); @@ -180,6 +208,8 @@ void QToc::select(string const & text) return; } + // Lop off counter part and save: + text_ = text.substr(text.find(' ') + 1); controller().goTo(*iter); } @@ -190,5 +220,34 @@ void QToc::set_depth(int depth) updateToc(depth); } + +void QToc::moveup() +{ + controller().outline(toc::Up); + updateToc(depth_); +} + + +void QToc::movedn() +{ + controller().outline(toc::Down); + updateToc(depth_); +} + + +void QToc::movein() +{ + controller().outline(toc::In); + updateToc(depth_); +} + + +void QToc::moveout() +{ + controller().outline(toc::Out); + updateToc(depth_); +} + + } // namespace frontend } // namespace lyx diff --git a/src/frontends/qt2/QToc.h b/src/frontends/qt2/QToc.h index 09c6b69a25..769bc9a766 100644 --- a/src/frontends/qt2/QToc.h +++ b/src/frontends/qt2/QToc.h @@ -33,6 +33,9 @@ private: /// update the listview void updateToc(int newdepth); + /// + bool canOutline(); + /// update the float types void updateType(); @@ -42,6 +45,15 @@ private: /// set the depth void set_depth(int depth); + /// Move header up/down/in/out in list (outlining) + void moveup(); + /// + void movedn(); + /// + void movein(); + /// + void moveout(); + virtual void apply() {} /// update dialog @@ -55,6 +67,12 @@ private: /// depth of list shown int depth_; + + /// Store selected item's string + std::string text_; + + /// Store ToC list type + std::string type_; }; } // namespace frontend diff --git a/src/frontends/qt2/QTocDialog.C b/src/frontends/qt2/QTocDialog.C index 0e92d89378..f276596f0e 100644 --- a/src/frontends/qt2/QTocDialog.C +++ b/src/frontends/qt2/QTocDialog.C @@ -32,8 +32,11 @@ QTocDialog::QTocDialog(QToc * form) if (w) w->hide(); - connect(closePB, SIGNAL(clicked()), - form, SLOT(slotClose())); + connect(closePB, SIGNAL(clicked()), form, SLOT(slotClose())); + connect(moveupPB, SIGNAL(clicked()), this, SLOT(moveup_adaptor())); + connect(movednPB, SIGNAL(clicked()), this, SLOT(movedn_adaptor())); + connect(moveinPB, SIGNAL(clicked()), this, SLOT(movein_adaptor())); + connect(moveoutPB, SIGNAL(clicked()), this, SLOT(moveout_adaptor())); } @@ -60,12 +63,50 @@ void QTocDialog::select_adaptor(QListViewItem * item) } +void QTocDialog::enableButtons(bool enable) +{ + updatePB->setEnabled(enable); + + if (!form_->canOutline()) + enable = false; + + moveupPB->setEnabled(enable); + movednPB->setEnabled(enable); + moveinPB->setEnabled(enable); + moveoutPB->setEnabled(enable); +} + + void QTocDialog::update_adaptor() { form_->update(); } +void QTocDialog::moveup_adaptor() +{ + form_->moveup(); +} + + +void QTocDialog::movedn_adaptor() +{ + form_->movedn(); +} + + +void QTocDialog::movein_adaptor() +{ + form_->movein(); +} + + +void QTocDialog::moveout_adaptor() +{ + form_->moveout(); +} + + void QTocDialog::closeEvent(QCloseEvent * e) { form_->slotWMHide(); diff --git a/src/frontends/qt2/QTocDialog.h b/src/frontends/qt2/QTocDialog.h index d028d8131c..d49fbb37c6 100644 --- a/src/frontends/qt2/QTocDialog.h +++ b/src/frontends/qt2/QTocDialog.h @@ -24,11 +24,17 @@ class QTocDialog : public QTocDialogBase { public: QTocDialog(QToc * form); ~QTocDialog(); + /// + void enableButtons(bool enable = true); public slots: void activate_adaptor(int); void depth_adaptor(int); void select_adaptor(QListViewItem *); void update_adaptor(); + void moveup_adaptor(); + void movedn_adaptor(); + void movein_adaptor(); + void moveout_adaptor(); protected: void closeEvent(QCloseEvent * e); private: diff --git a/src/frontends/qt2/ui/QTocDialogBase.ui b/src/frontends/qt2/ui/QTocDialogBase.ui index 5eb58f606e..99f1f2467e 100644 --- a/src/frontends/qt2/ui/QTocDialogBase.ui +++ b/src/frontends/qt2/ui/QTocDialogBase.ui @@ -168,7 +168,51 @@ text - &Update + U&pdate + + + + QPushButton + + name + moveupPB + + + text + &Up + + + + QPushButton + + name + movednPB + + + text + &Down + + + + QPushButton + + name + moveinPB + + + text + &In + + + + QPushButton + + name + moveoutPB + + + text + &Out diff --git a/src/lfuns.h b/src/lfuns.h index f3cef5ac1e..7d866e9808 100644 --- a/src/lfuns.h +++ b/src/lfuns.h @@ -357,6 +357,11 @@ enum kb_action { LFUN_BIBDB_ADD, LFUN_BIBDB_DEL, LFUN_INSERT_CITATION, + LFUN_OUTLINE_UP, // Vermeer 20060323 + // 275 + LFUN_OUTLINE_DOWN, + LFUN_OUTLINE_IN, + LFUN_OUTLINE_OUT, LFUN_TOGGLE_COMPRESSION, // bpeng 20060427 // 275 LFUN_INSET_DISSOLVE, // jspitzm 20060807 diff --git a/src/toc.C b/src/toc.C index d90cab6e37..114c5d3bfc 100644 --- a/src/toc.C +++ b/src/toc.C @@ -15,11 +15,12 @@ #include "buffer.h" #include "bufferparams.h" +#include "cursor.h" #include "FloatList.h" #include "funcrequest.h" #include "LyXAction.h" #include "paragraph.h" -#include "pariterator.h" +#include "undo.h" #include "frontends/LyXView.h" @@ -167,5 +168,111 @@ void asciiTocList(string const & type, Buffer const & buffer, ostream & os) } +void outline(OutlineOp mode, LCursor & cur) +{ + recordUndo(cur); + Buffer * buf = & cur.buffer(); + pit_type & pit = cur.pit(); + ParagraphList & pars = buf->text().paragraphs(); + ParagraphList::iterator bgn = pars.begin(); + ParagraphList::iterator s = boost::next(bgn, pit); + ParagraphList::iterator p = s; + ParagraphList::iterator end = pars.end(); + + LyXTextClass::const_iterator lit = + buf->params().getLyXTextClass().begin(); + LyXTextClass::const_iterator const lend = + buf->params().getLyXTextClass().end(); + + int const thistoclevel = s->layout()->toclevel; + int toclevel; + switch (mode) { + case Up: { + if (p != end) + ++p; + for (; p != end; ++p) { + toclevel = p->layout()->toclevel; + if (toclevel != LyXLayout::NOT_IN_TOC + && toclevel <= thistoclevel) { + break; + } + } + ParagraphList::iterator q = s; + if (q != bgn) + --q; + else + break; + for (; q != bgn; --q) { + toclevel = q->layout()->toclevel; + if (toclevel != LyXLayout::NOT_IN_TOC + && toclevel <= thistoclevel) { + break; + } + } + pit_type const newpit = std::distance(pars.begin(), q); + pit_type const len = std::distance(s, p); + pit += len; + pars.insert(q, s, p); + s = boost::next(pars.begin(), pit); + ParagraphList::iterator t = boost::next(s, len); + pit = newpit; + pars.erase(s, t); + break; + } + case Down: { + if (p != end) + ++p; + for (; p != end; ++p) { + toclevel = p->layout()->toclevel; + if (toclevel != LyXLayout::NOT_IN_TOC + && toclevel <= thistoclevel) { + break; + } + } + ParagraphList::iterator q = p; + if (q != end) + ++q; + else + break; + for (; q != end; ++q) { + toclevel = q->layout()->toclevel; + if (toclevel != LyXLayout::NOT_IN_TOC + && toclevel <= thistoclevel) { + break; + } + } + pit_type const newpit = std::distance(pars.begin(), q); + pit_type const len = std::distance(s, p); + pars.insert(q, s, p); + s = boost::next(pars.begin(), pit); + ParagraphList::iterator t = boost::next(s, len); + pit = newpit - len; + pars.erase(s, t); + break; + } + case In: + for (; lit != lend; ++lit) { + if ((*lit)->toclevel == thistoclevel + 1 && + s->layout()->labeltype == (*lit)->labeltype) { + s->layout((*lit)); + break; + } + } + break; + case Out: + for (; lit != lend; ++lit) { + if ((*lit)->toclevel == thistoclevel - 1 && + s->layout()->labeltype == (*lit)->labeltype) { + s->layout((*lit)); + break; + } + } + break; + default: + break; + } +} + + } // namespace toc } // namespace lyx diff --git a/src/toc.h b/src/toc.h index f0f2f80262..3d359a081a 100644 --- a/src/toc.h +++ b/src/toc.h @@ -20,6 +20,8 @@ #include #include +#include "pariterator.h" + class Buffer; class LyXView; class Paragraph; @@ -72,8 +74,7 @@ std::string const getGuiName(std::string const & type, Buffer const &); inline bool operator==(TocItem const & a, TocItem const & b) { - return a.id_ == b.id_ && a.str == b.str; - // No need to compare depth. + return a.id_ == b.id_ && a.str == b.str && a.depth == b.depth; } @@ -84,6 +85,18 @@ bool operator!=(TocItem const & a, TocItem const & b) } +/// the type of outline operation +enum OutlineOp { + Up, // Move this header with text down + Down, // Move this header with text up + In, // Make this header deeper + Out // Make this header shallower +}; + + +void outline(OutlineOp, LCursor &); + + } // namespace toc } // namespace lyx diff --git a/status.14x b/status.14x index bf5ee6b3fb..49ecec73ee 100644 --- a/status.14x +++ b/status.14x @@ -27,6 +27,8 @@ What's new - Update Romanian localization of the interface. +- Outline support. + ** Bug fixes: * Document Input/Output