fb2tree.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. #include "fb2tree.hpp"
  2. #include <QtDebug>
  3. #include <QAction>
  4. #include <QApplication>
  5. #include <QCursor>
  6. #include <QVBoxLayout>
  7. #include <QWebFrame>
  8. #include <QWebPage>
  9. #include <QTreeView>
  10. #include <QUrl>
  11. #include "fb2text.hpp"
  12. #include "fb2html.h"
  13. #include "fb2utils.h"
  14. //---------------------------------------------------------------------------
  15. // Fb2TreeItem
  16. //---------------------------------------------------------------------------
  17. Fb2TreeItem::Fb2TreeItem(QWebElement &element, Fb2TreeItem *parent, int number)
  18. : QObject(parent)
  19. , m_element(element)
  20. , m_parent(parent)
  21. , m_number(number)
  22. {
  23. init();
  24. addChildren(element);
  25. }
  26. Fb2TreeItem::~Fb2TreeItem()
  27. {
  28. foreach (Fb2TreeItem * item, m_list) {
  29. delete item;
  30. }
  31. }
  32. void Fb2TreeItem::init()
  33. {
  34. m_text = QString();
  35. m_name = m_element.tagName().toLower();
  36. QString style = m_element.attribute("class").toLower();
  37. if (m_name == "div") {
  38. if (style == "title") {
  39. m_text = title();
  40. if (m_parent) m_parent->m_text += m_text += " ";
  41. } else if (style == "subtitle") {
  42. m_text = title();
  43. } else if (style == "body") {
  44. m_body = m_element.attribute("fb2_name");
  45. }
  46. if (!style.isEmpty()) m_name = style;
  47. } else if (m_name == "img") {
  48. m_name = "image";
  49. QUrl url = m_element.attribute("src");
  50. m_text = url.fragment();
  51. }
  52. }
  53. QString Fb2TreeItem::title()
  54. {
  55. return m_element.toPlainText().left(255).simplified();
  56. }
  57. void Fb2TreeItem::addChildren(QWebElement &parent, bool direct, bool header)
  58. {
  59. int number = 0;
  60. QWebElement child = parent.firstChild();
  61. while (!child.isNull()) {
  62. QString tag = child.tagName().toLower();
  63. if (tag == "div") {
  64. bool h = header;
  65. QString style = child.attribute("class").toLower();
  66. h = h || style == "description" || style == "stylesheet";
  67. if (!h || style == "annotation" || style == "history") {
  68. m_list << new Fb2TreeItem(child, this, direct ? number : -1);
  69. } else {
  70. addChildren(child, false, h);
  71. }
  72. } else if (header) {
  73. // skip
  74. } else if (tag == "img") {
  75. m_list << new Fb2TreeItem(child, this, direct ? number : -1);
  76. } else {
  77. addChildren(child, false, header);
  78. }
  79. child = child.nextSibling();
  80. number++;
  81. }
  82. }
  83. Fb2TreeItem * Fb2TreeItem::item(const QModelIndex &index) const
  84. {
  85. int row = index.row();
  86. if (row < 0 || row >= m_list.size()) return NULL;
  87. return m_list[row];
  88. }
  89. Fb2TreeItem * Fb2TreeItem::item(int row) const
  90. {
  91. if (row < 0 || row >= m_list.size()) return NULL;
  92. return m_list[row];
  93. }
  94. QString Fb2TreeItem::text() const
  95. {
  96. QString name = m_name;
  97. if (!m_body.isEmpty()) name += " name=" + m_body;
  98. return QString("<%1> %2").arg(name).arg(m_text);
  99. }
  100. QString Fb2TreeItem::selector() const
  101. {
  102. QString text = "";
  103. QString selector = ".get(0)";
  104. QWebElement element = m_element;
  105. QWebElement parent = element.parent();
  106. while (!parent.isNull()) {
  107. text.prepend(element.tagName()).prepend("/");
  108. QWebElement child = parent.firstChild();
  109. int index = -1;
  110. while (!child.isNull()) {
  111. index++;
  112. if (child == element) break;
  113. child = child.nextSibling();
  114. }
  115. if (index == -1) return QString();
  116. selector.prepend(QString(".children().eq(%1)").arg(index));
  117. element = parent;
  118. parent = element.parent();
  119. }
  120. return selector.prepend("$('html')");
  121. }
  122. Fb2TreeItem * Fb2TreeItem::content(const Fb2TreeModel &model, int number, QModelIndex &index) const
  123. {
  124. int row = 0;
  125. QList<Fb2TreeItem*>::const_iterator i;
  126. for (i = m_list.constBegin(); i != m_list.constEnd(); ++i) {
  127. if ((*i)->m_number == number) {
  128. index = model.index(row, 0, index);
  129. return *i;
  130. }
  131. row++;
  132. }
  133. return 0;
  134. }
  135. //---------------------------------------------------------------------------
  136. // Fb2TreeModel
  137. //---------------------------------------------------------------------------
  138. Fb2TreeModel::Fb2TreeModel(Fb2TextEdit &view, QObject *parent)
  139. : QAbstractItemModel(parent)
  140. , m_view(view)
  141. , m_root(NULL)
  142. {
  143. QWebElement doc = view.page()->mainFrame()->documentElement();
  144. QWebElement body = doc.findFirst("body");
  145. if (body.isNull()) return;
  146. m_root = new Fb2TreeItem(body);
  147. }
  148. Fb2TreeModel::~Fb2TreeModel()
  149. {
  150. if (m_root) delete m_root;
  151. }
  152. Fb2TreeItem * Fb2TreeModel::item(const QModelIndex &index) const
  153. {
  154. if (index.isValid()) {
  155. return static_cast<Fb2TreeItem*>(index.internalPointer());
  156. } else {
  157. return m_root;
  158. }
  159. }
  160. int Fb2TreeModel::columnCount(const QModelIndex &parent) const
  161. {
  162. Q_UNUSED(parent);
  163. return 1;
  164. }
  165. QModelIndex Fb2TreeModel::index(Fb2TreeItem *item, int column) const
  166. {
  167. Fb2TreeItem *parent = item->parent();
  168. return parent ? createIndex(parent->index(item), column, (void*)item) : QModelIndex();
  169. }
  170. QModelIndex Fb2TreeModel::index(int row, int column, const QModelIndex &parent) const
  171. {
  172. if (!m_root || row < 0 || column < 0) return QModelIndex();
  173. if (Fb2TreeItem *owner = item(parent)) {
  174. if (Fb2TreeItem *child = owner->item(row)) {
  175. return createIndex(row, column, (void*)child);
  176. }
  177. }
  178. return QModelIndex();
  179. }
  180. QModelIndex Fb2TreeModel::parent(const QModelIndex &child) const
  181. {
  182. if (Fb2TreeItem * node = static_cast<Fb2TreeItem*>(child.internalPointer())) {
  183. if (Fb2TreeItem * parent = node->parent()) {
  184. if (Fb2TreeItem * owner = parent->parent()) {
  185. return createIndex(owner->index(parent), 0, (void*)parent);
  186. }
  187. }
  188. }
  189. return QModelIndex();
  190. }
  191. int Fb2TreeModel::rowCount(const QModelIndex &parent) const
  192. {
  193. if (parent.column() > 0) return 0;
  194. Fb2TreeItem *owner = item(parent);
  195. return owner ? owner->count() : 0;
  196. }
  197. QVariant Fb2TreeModel::data(const QModelIndex &index, int role) const
  198. {
  199. if (role != Qt::DisplayRole) return QVariant();
  200. Fb2TreeItem * i = item(index);
  201. return i ? i->text() : QVariant();
  202. }
  203. void Fb2TreeModel::selectText(const QModelIndex &index)
  204. {
  205. if (Fb2TreeItem *node = item(index)) {
  206. node->element().select();
  207. }
  208. }
  209. QModelIndex Fb2TreeModel::index(const QString &location) const
  210. {
  211. QModelIndex index;
  212. Fb2TreeItem * parent = m_root;
  213. QStringList list = location.split(",");
  214. QStringListIterator iterator(list);
  215. while (parent && iterator.hasNext()) {
  216. QString str = iterator.next();
  217. if (str.left(5) == "HTML=") continue;
  218. int key = str.mid(str.indexOf("=")+1).toInt();
  219. Fb2TreeItem * child = parent->content(*this, key, index);
  220. parent = child;
  221. }
  222. return index;
  223. }
  224. QModelIndex Fb2TreeModel::move(const QModelIndex &index, int dx, int dy)
  225. {
  226. Fb2TreeItem *child = item(index);
  227. if (!child) return QModelIndex();
  228. Fb2TreeItem *owner = child->parent();
  229. if (!owner) return QModelIndex();
  230. int from = index.row();
  231. QModelIndex parent = this->parent(index);
  232. QModelIndex result;
  233. switch (dx) {
  234. case -1: {
  235. if (!owner || owner == m_root) return QModelIndex();
  236. if (child->name() != "section") return QModelIndex();
  237. if (owner->name() != "section") return QModelIndex();
  238. QModelIndex target = this->parent(parent);
  239. int to = parent.row() + 1;
  240. result = createIndex(to, 0, (void*)child);
  241. beginMoveRows(parent, from, from, target, to);
  242. QWebElement element = child->element().takeFromDocument();
  243. owner->element().appendOutside(element);
  244. owner->takeAt(from);
  245. owner->parent()->insert(child, to);
  246. endMoveRows();
  247. } break;
  248. case +1: {
  249. if (from == 0) return QModelIndex();
  250. Fb2TreeItem * brother = owner->item(from - 1);
  251. if (child->name() != "section") return QModelIndex();
  252. if (brother->name() != "section") return QModelIndex();
  253. QModelIndex target = createIndex(from - 1, 0, (void*)brother);
  254. int to = rowCount(target);
  255. result = createIndex(to, 0, (void*)child);
  256. beginMoveRows(parent, from, from, target, to);
  257. QWebElement element = child->element().takeFromDocument();
  258. brother->element().appendInside(element);
  259. owner->takeAt(from);
  260. brother->insert(child, to);
  261. endMoveRows();
  262. } break;
  263. default: {
  264. int to = from + dy;
  265. if (to < 0 || rowCount(parent) <= to) return QModelIndex();
  266. result = createIndex(to, 0, (void*)child);
  267. if (dy > 0) {
  268. to = index.row();
  269. from = to + dy;
  270. }
  271. Fb2TreeItem * child = owner->item(to);
  272. Fb2TreeItem * brother = owner->item(from);
  273. QString n = child->name();
  274. bool ok = (n == "body" || n == "section") && n == brother->name();
  275. if (!ok) return QModelIndex();
  276. beginMoveRows(parent, from, from, parent, to);
  277. brother = owner->takeAt(from);
  278. owner->insert(brother, to);
  279. QWebElement element = child->element().takeFromDocument();
  280. brother->element().appendOutside(element);
  281. endMoveRows();
  282. } break;
  283. }
  284. return result;
  285. }
  286. bool Fb2TreeModel::removeRows(int row, int count, const QModelIndex &parent)
  287. {
  288. if (row < 0 || count <= 0 || row + count > rowCount(parent)) return false;
  289. Fb2TreeItem * owner = item(parent);
  290. if (!owner) return false;
  291. int last = row + count - 1;
  292. beginRemoveRows(parent, row, last);
  293. for (int i = last; i >= row; i--) {
  294. if (Fb2TreeItem * child = owner->takeAt(i)) {
  295. Fb2TextPage & page = *m_view.page();
  296. page.undoStack()->beginMacro("Delete element");
  297. page.undoStack()->push(new Fb2DeleteCmd(page, child->element()));
  298. page.undoStack()->endMacro();
  299. delete child;
  300. }
  301. }
  302. endRemoveRows();
  303. return true;
  304. }
  305. void Fb2TreeModel::children(QWebElement parent, Fb2ElementList &list)
  306. {
  307. QWebElement child = parent.firstChild();
  308. while (!child.isNull()) {
  309. QString tag = child.tagName().toLower();
  310. if (tag == "div") {
  311. list << child;
  312. } else if (tag == "img") {
  313. list << child;
  314. } else {
  315. children(child, list);
  316. }
  317. child = child.nextSibling();
  318. }
  319. }
  320. void Fb2TreeModel::update(Fb2TreeItem &owner)
  321. {
  322. owner.init();
  323. Fb2ElementList list;
  324. children(owner.element(), list);
  325. int pos = 0;
  326. QModelIndex index = this->index(&owner);
  327. for (QList<QWebElement>::iterator it = list.begin(); it != list.end(); it++) {
  328. Fb2TreeItem * child = 0;
  329. QWebElement element = *it;
  330. int count = owner.count();
  331. for (int i = pos; i < count; i++) {
  332. if (owner.item(i)->element() == element) {
  333. child = owner.item(i);
  334. if (i > pos) {
  335. beginMoveRows(index, i, i, index, pos);
  336. owner.insert(owner.takeAt(i), pos);
  337. endMoveRows();
  338. break;
  339. }
  340. }
  341. }
  342. if (child) {
  343. QString old = child->text();
  344. update(*child);
  345. if (old != child->text()) {
  346. QModelIndex i = this->index(child);
  347. emit dataChanged(i, i);
  348. }
  349. } else {
  350. Fb2TreeItem * child = new Fb2TreeItem(element);
  351. beginInsertRows(index, pos, pos);
  352. owner.insert(child, pos);
  353. endInsertRows();
  354. }
  355. pos++;
  356. }
  357. int last = owner.count() - 1;
  358. if (pos <= last) {
  359. beginRemoveRows(index, pos, last);
  360. for (int i = last; i >= pos; i--) delete owner.takeAt(i);
  361. endRemoveRows();
  362. }
  363. }
  364. void Fb2TreeModel::update()
  365. {
  366. if (!m_root) return;
  367. QWebElement doc = m_view.page()->mainFrame()->documentElement();
  368. QWebElement body = doc.findFirst("body");
  369. if (m_root->element() != body) *m_root = body;
  370. update(*m_root);
  371. }
  372. //---------------------------------------------------------------------------
  373. // Fb2TreeView
  374. //---------------------------------------------------------------------------
  375. Fb2TreeView::Fb2TreeView(Fb2TextEdit &view, QWidget *parent)
  376. : QTreeView(parent)
  377. , m_view(view)
  378. {
  379. setHeaderHidden(true);
  380. setContextMenuPolicy(Qt::CustomContextMenu);
  381. connect(this, SIGNAL(activated(QModelIndex)), SLOT(activated(QModelIndex)));
  382. connect(m_view.page(), SIGNAL(loadFinished(bool)), SLOT(updateTree()));
  383. connect(m_view.page(), SIGNAL(contentsChanged()), SLOT(contentsChanged()));
  384. connect(m_view.page(), SIGNAL(selectionChanged()), SLOT(selectionChanged()));
  385. connect(this, SIGNAL(customContextMenuRequested(QPoint)), SLOT(contextMenu(QPoint)));
  386. m_timerSelect.setInterval(1000);
  387. m_timerSelect.setSingleShot(true);
  388. connect(&m_timerSelect, SIGNAL(timeout()), SLOT(selectTree()));
  389. m_timerUpdate.setInterval(1000);
  390. m_timerUpdate.setSingleShot(true);
  391. connect(&m_timerUpdate, SIGNAL(timeout()), SLOT(updateTree()));
  392. QMetaObject::invokeMethod(this, "updateTree", Qt::QueuedConnection);
  393. }
  394. void Fb2TreeView::initActions(QToolBar *toolbar)
  395. {
  396. QAction * act;
  397. act = new QAction(FB2::icon("list-add"), tr("&Insert"), this);
  398. act->setShortcutContext(Qt::WidgetShortcut);
  399. act->setShortcut(Qt::Key_Insert);
  400. act->setPriority(QAction::LowPriority);
  401. connect(act, SIGNAL(triggered()), SLOT(insertNode()));
  402. toolbar->addAction(act);
  403. m_menu.addAction(act);
  404. act = new QAction(FB2::icon("list-remove"), tr("&Delete"), this);
  405. act->setShortcutContext(Qt::WidgetShortcut);
  406. act->setShortcut(Qt::Key_Delete);
  407. act->setPriority(QAction::LowPriority);
  408. connect(act, SIGNAL(triggered()), SLOT(deleteNode()));
  409. toolbar->addAction(act);
  410. m_menu.addAction(act);
  411. m_menu.addSeparator();
  412. actionCut = act = new QAction(FB2::icon("edit-cut"), tr("Cu&t"), this);
  413. act->setShortcutContext(Qt::WidgetShortcut);
  414. act->setPriority(QAction::LowPriority);
  415. act->setShortcuts(QKeySequence::Cut);
  416. act->setEnabled(false);
  417. m_menu.addAction(act);
  418. actionCopy = act = new QAction(FB2::icon("edit-copy"), tr("&Copy"), this);
  419. act->setShortcutContext(Qt::WidgetShortcut);
  420. act->setPriority(QAction::LowPriority);
  421. act->setShortcuts(QKeySequence::Copy);
  422. act->setEnabled(false);
  423. m_menu.addAction(act);
  424. actionPaste = act = new QAction(FB2::icon("edit-paste"), tr("&Paste"), this);
  425. act->setShortcutContext(Qt::WidgetShortcut);
  426. act->setPriority(QAction::LowPriority);
  427. act->setShortcuts(QKeySequence::Paste);
  428. m_menu.addAction(act);
  429. toolbar->addSeparator();
  430. m_menu.addSeparator();
  431. act = new QAction(FB2::icon("go-up"), tr("&Up"), this);
  432. act->setShortcutContext(Qt::WidgetShortcut);
  433. act->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));
  434. connect(act, SIGNAL(triggered()), SLOT(moveUp()));
  435. toolbar->addAction(act);
  436. m_menu.addAction(act);
  437. act = new QAction(FB2::icon("go-down"), tr("&Down"), this);
  438. act->setShortcutContext(Qt::WidgetShortcut);
  439. act->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Down));
  440. connect(act, SIGNAL(triggered()), SLOT(moveDown()));
  441. toolbar->addAction(act);
  442. m_menu.addAction(act);
  443. act = new QAction(FB2::icon("go-previous"), tr("&Left"), this);
  444. act->setShortcutContext(Qt::WidgetShortcut);
  445. act->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Left));
  446. connect(act, SIGNAL(triggered()), SLOT(moveLeft()));
  447. toolbar->addAction(act);
  448. m_menu.addAction(act);
  449. act = new QAction(FB2::icon("go-next"), tr("&Right"), this);
  450. act->setShortcutContext(Qt::WidgetShortcut);
  451. act->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Right));
  452. connect(act, SIGNAL(triggered()), SLOT(moveRight()));
  453. toolbar->addAction(act);
  454. m_menu.addAction(act);
  455. }
  456. void Fb2TreeView::keyPressEvent(QKeyEvent *event)
  457. {
  458. if (event->modifiers() == Qt::NoModifier) {
  459. switch (event->key()) {
  460. case Qt::Key_Insert: insertNode(); return;
  461. case Qt::Key_Delete: deleteNode(); return;
  462. }
  463. }
  464. QTreeView::keyPressEvent(event);
  465. }
  466. void Fb2TreeView::contextMenu(const QPoint &pos)
  467. {
  468. m_menu.exec(QCursor::pos());
  469. }
  470. void Fb2TreeView::selectionChanged()
  471. {
  472. m_timerSelect.start();
  473. }
  474. void Fb2TreeView::contentsChanged()
  475. {
  476. m_timerUpdate.start();
  477. }
  478. void Fb2TreeView::activated(const QModelIndex &index)
  479. {
  480. if (qApp->focusWidget() == &m_view) return;
  481. if (Fb2TreeModel * m = model()) {
  482. m->selectText(index);
  483. }
  484. }
  485. void Fb2TreeView::selectTree()
  486. {
  487. if (qApp->focusWidget() == this) return;
  488. if (Fb2TreeModel * m = model()) {
  489. QString location = m->view().page()->location();
  490. QModelIndex index = m->index(location);
  491. if (!index.isValid()) return;
  492. setCurrentIndex(index);
  493. scrollTo(index);
  494. }
  495. }
  496. void Fb2TreeView::updateTree()
  497. {
  498. if (Fb2TreeModel * m = model()) {
  499. m->update();
  500. } else {
  501. m = new Fb2TreeModel(m_view, this);
  502. setModel(m);
  503. }
  504. selectTree();
  505. }
  506. QModelIndex Fb2TreeModel::append(const QModelIndex &parent)
  507. {
  508. Fb2TreeItem * owner = item(parent);
  509. if (!owner || owner == m_root) return QModelIndex();
  510. int row = owner->count();
  511. owner->element().appendInside("<div class=section><div class=title><p><br/></p></div><p><br/></p></div>");
  512. QWebElement element = owner->element().lastChild();
  513. Fb2TreeItem * child = new Fb2TreeItem(element);
  514. beginInsertRows(parent, row, row);
  515. owner->insert(child, row);
  516. endInsertRows();
  517. return createIndex(row, 0, (void*)child);
  518. }
  519. void Fb2TreeView::insertNode()
  520. {
  521. if (Fb2TreeModel * m = model()) {
  522. QModelIndex index = currentIndex();
  523. Fb2TreeItem * item = m->item(index);
  524. if (!item) return;
  525. QString n = item->name();
  526. if (n != "section" && n != "body") {
  527. index = m->parent(index);
  528. item = item->parent();
  529. n = item->name();
  530. if (n != "section" && n != "body") return;
  531. }
  532. QModelIndex result = m->append(index);
  533. if (!result.isValid()) return;
  534. setCurrentIndex(result);
  535. emit QTreeView::currentChanged(result, index);
  536. emit QTreeView::activated(result);
  537. scrollTo(result);
  538. }
  539. }
  540. void Fb2TreeView::deleteNode()
  541. {
  542. if (Fb2TreeModel * m = model()) {
  543. QModelIndex index = currentIndex();
  544. QModelIndex result = m->parent(index);
  545. setCurrentIndex(result);
  546. emit currentChanged(result, index);
  547. emit QTreeView::activated(result);
  548. m->removeRow(index.row(), result);
  549. scrollTo(result);
  550. }
  551. }
  552. Fb2TreeModel * Fb2TreeView::model()
  553. {
  554. return qobject_cast<Fb2TreeModel*>(QTreeView::model());
  555. }
  556. void Fb2TreeView::moveCurrent(int dx, int dy)
  557. {
  558. if (Fb2TreeModel * m = model()) {
  559. QModelIndex index = currentIndex();
  560. QModelIndex result = m->move(index, dx, dy);
  561. if (result.isValid()) {
  562. setCurrentIndex(result);
  563. emit currentChanged(result, index);
  564. emit QTreeView::activated(result);
  565. scrollTo(result);
  566. }
  567. }
  568. }
  569. void Fb2TreeView::moveUp()
  570. {
  571. moveCurrent(0, -1);
  572. }
  573. void Fb2TreeView::moveDown()
  574. {
  575. moveCurrent(0, +1);
  576. }
  577. void Fb2TreeView::moveLeft()
  578. {
  579. moveCurrent(-1, 0);
  580. }
  581. void Fb2TreeView::moveRight()
  582. {
  583. moveCurrent(+1, 0);
  584. }
  585. //---------------------------------------------------------------------------
  586. // Fb2TreeWidget
  587. //---------------------------------------------------------------------------
  588. Fb2TreeWidget::Fb2TreeWidget(Fb2TextEdit &view, QWidget* parent)
  589. : QWidget(parent)
  590. {
  591. QVBoxLayout * layout = new QVBoxLayout(this);
  592. layout->setSpacing(0);
  593. layout->setContentsMargins(0, 0, 0, 0);
  594. layout->setObjectName(QString::fromUtf8("verticalLayout"));
  595. m_tree = new Fb2TreeView(view, this);
  596. layout->addWidget(m_tree);
  597. m_tool = new QToolBar(this);
  598. layout->addWidget(m_tool);
  599. m_tree->initActions(m_tool);
  600. }