[KLF Application][KLF Tools][KLF Backend][KLF Home]
KLatexFormula Project
klflibview_p.h
Go to the documentation of this file.
1 /***************************************************************************
2  * file klflibview_p.h
3  * This file is part of the KLatexFormula Project.
4  * Copyright (C) 2011 by Philippe Faist
5  * philippe.faist at bluewin.ch
6  * *
7  * This program is free software; you can redistribute it and/or modify *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or *
10  * (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License *
18  * along with this program; if not, write to the *
19  * Free Software Foundation, Inc., *
20  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21  ***************************************************************************/
22 /* $Id: klflibview_p.h 754 2012-01-05 21:56:47Z phfaist $ */
23 
24 
30 #ifndef KLFLIBVIEW_P_H
31 #define KLFLIBVIEW_P_H
32 
33 #include <math.h> // abs()
34 
35 #include <QApplication>
36 #include <QStringList>
37 #include <QAbstractItemView>
38 #include <QTreeView>
39 #include <QListView>
40 #include <QMimeData>
41 #include <QDrag>
42 #include <QDragEnterEvent>
43 #include <QDragMoveEvent>
44 #include <QDropEvent>
45 #include <QWidget>
46 #include <QFileInfo>
47 #include <QFileDialog>
48 #include <QDir>
49 #include <QDesktopServices>
50 #include <QDirModel>
51 #include <QCompleter>
52 
53 #include <ui_klfliblocalfilewidget.h>
54 
55 #include "klflib.h"
56 #include "klflibview.h"
57 #include "klfconfig.h"
58 
59 class KLFLibDefTreeView;
60 
61 
63 inline QPointF sizeToPointF(const QSizeF& s) { return QPointF(s.width(), s.height()); }
65 inline QSizeF pointToSizeF(const QPointF& p) { return QSizeF(p.x(), p.y()); }
66 
67 
68 // -----------------------------
69 
70 
73 {
74 public:
75  typedef qint32 IndexType;
83  typedef quint32 UIDType;
84  static const quint8 UIDKindShift = 30;
85  static const UIDType UIDKindMask = 0xC0000000;
86  static const UIDType UIDIndexMask = 0x3FFFFFFF;
87  static const UIDType UIDInvalid = 0xFFFFFFFF;
88 
89  enum ItemKind {
92  };
93 
94  struct NodeId {
95  NodeId(ItemKind k = ItemKind(EntryKind), IndexType i = -1) : kind(k), index(i) { }
96  bool valid() const { return index >= 0; }
97  bool isRoot() const { return kind == CategoryLabelKind && index == 0; }
100  bool operator==(const NodeId& other) const {
101  return kind == other.kind && index == other.index;
102  }
103  bool operator!=(const NodeId& other) const {
104  return !(operator==(other));
105  }
107  if ( index < 0 ) // invalid index
108  return (~0x0); // 0xFFFFFFFF
109  UIDType uid = (UIDType)index;
110  uid |= (kind << UIDKindShift);
111  return uid;
112  }
113  static NodeId fromUID(UIDType uid) {
114  return NodeId((ItemKind)((uid&UIDKindMask)>>UIDKindShift), uid&UIDIndexMask);
115  }
116  static NodeId rootNode() { return NodeId(CategoryLabelKind, 0); }
117  };
118  struct Node {
119  Node() : allocated(false) { }
121  allChildrenFetched(false) { }
122  Node(const Node& other) : allocated(other.allocated), kind(other.kind), parent(other.parent),
124  virtual ~Node() { }
126  bool allocated;
133  };
134  struct EntryNode : public Node {
136  {
137  allChildrenFetched = true; // no children to fetch
138  }
139  EntryNode(const EntryNode& copy)
140  : Node(copy), entryid(copy.entryid), minimalist(copy.minimalist), entry(copy.entry) { }
141 
142  inline bool entryIsValid() const { return allocated && parent != NodeId() && entryid >= 0; }
143 
148  };
149  struct CategoryLabelNode : public Node {
157  };
158 
159  template<class N>
160  class NodeCache : public QList<N> {
161  public:
162  NodeCache() : QList<N>(), pContainsNonAllocated(false) { }
163 
164  inline bool isAllocated(IndexType i) { return QList<N>::at(i).allocated; }
165 
166  IndexType insertNewNode(const N& n) {
167  IndexType insertPos = QList<N>::size();
168  if (pContainsNonAllocated) {
169  // walk the cache, and find an invalid node
170  for (insertPos = 0; insertPos < QList<N>::size() && QList<N>::at(insertPos).allocated; ++insertPos)
171  ;
172  }
173  if (insertPos == QList<N>::size()) {
174  pContainsNonAllocated = false;
175  this->append(n);
176  return insertPos;
177  }
178  QList<N>::operator[](insertPos) = n;
179  return insertPos;
180  }
181 
183  inline void unlinkNode(const NodeId& nid) { unlinkNode(nid.index); }
184  void unlinkNode(IndexType index) {
185  N& node = QList<N>::operator[](index);
186  node.allocated = false; // render invalid
187  pContainsNonAllocated = true;
188  }
189 
191  inline N takeNode(const NodeId& nid) { return takeNode(nid.index); }
192  N takeNode(IndexType index) {
193  if (index < 0 || index >= QList<N>::size()) {
194  qWarning()<<KLF_FUNC_NAME<<": invalid index="<<index;
195  return N();
196  }
197  N node = QList<N>::at(index);
198  unlinkNode(index);
199  return node;
200  }
201  private:
202  bool pContainsNonAllocated;
203  };
204 
207 
208  EntryNode pInvalidEntryNode; // not initialized, not used except for return values
209  // of functions aborting their call eg. getNodeRef()
210 
211 
213  : pModel(model)
214  {
215  pIsFetchingMore = false;
216 
217  pLastSortPropId = KLFLibEntry::DateTime;
218  pLastSortOrder = Qt::DescendingOrder;
219  }
220 
221  virtual ~KLFLibModelCache() { }
222 
224 
225  void rebuildCache();
226 
229  QModelIndex createIndexFromId(NodeId nodeid, int row, int column);
230 
232  NodeId getNodeForIndex(const QModelIndex& index);
234  Node getNode(NodeId nodeid);
235  Node& getNodeRef(NodeId nodeid);
236  EntryNode& getEntryNodeRef(NodeId nodeid, bool requireNotMinimalist = false);
238 
240  int getNodeRow(NodeId nodeid);
241 
250  }
251 
256  void ensureNotMinimalist(NodeId nodeId, int count = -1);
257 
258  bool canFetchMore(NodeId parentId);
259  void fetchMore(NodeId parentId, int batchCount = -1);
260 
261  void updateData(const QList<KLFLib::entryId>& entryIdList, int modifyType);
262 
274  void treeInsertEntry(const EntryNode& e, bool isRebuildingCache = false);
275 
280  EntryNode treeTakeEntry(const NodeId& e, bool notifyQtApi = true);
281 
289  IndexType cacheFindCategoryLabel(QStringList catelements, bool createIfNotExists = false,
290  bool notifyQtApi = false, bool newlyCreatedAreChildrenFetched = true);
291 
292  class KLF_EXPORT KLFLibModelSorter
293  {
294  public:
295  KLFLibModelSorter(KLFLibModelCache *c, KLFLibEntrySorter *es, bool groupcategories)
296  : cache(c), entrysorter(es), groupCategories(groupcategories)
297  {
298  }
300  bool operator()(const NodeId& a, const NodeId& b);
301 
302  KLFLibEntrySorter *entrySorter() { return entrysorter; }
303 
304  private:
305  KLFLibModelCache *cache;
306  KLFLibEntrySorter *entrysorter;
307  bool groupCategories;
308  };
309 
311  QString nodeValue(NodeId node, int propId = KLFLibEntry::Latex);
312 
315  bool searchNodeMatches(const NodeId& nodeId, const QString& searchString, Qt::CaseSensitivity cs);
316 
318  void setSortingBy(int propId, Qt::SortOrder order)
319  {
320  pLastSortPropId = propId;
321  pLastSortOrder = order;
322  }
323 
325  void sortCategory(NodeId category, KLFLibModelSorter *sorter, bool rootCall = true);
326 
334  NodeId nextNode(NodeId n);
339  NodeId prevNode(NodeId n);
346  NodeId lastNode(NodeId n);
347 
350  QList<KLFLib::entryId> entryIdList(const QModelIndexList& indexlist);
351 
354  QList<KLFLib::entryId> entryIdForIndexList(const QModelIndexList& indexlist);
355  QModelIndexList findEntryIdList(const QList<KLFLib::entryId>& eidlist);
356 
357  NodeId findEntryId(KLFLib::entryId eId);
358 
359  QStringList categoryListCache() { return pCatListCache; }
360 
361  void fullDump();
362  void dumpNodeTree(NodeId node, int indent = 0);
363 
364 private:
365  EntryCache pEntryCache;
366  CategoryLabelCache pCategoryLabelCache;
367 
368  QStringList pCatListCache;
369 
372  void insertCategoryStringInSuggestionCache(const QString& category)
373  {
374  insertCategoryStringInSuggestionCache(category.split('/', QString::SkipEmptyParts));
375  }
378  void insertCategoryStringInSuggestionCache(const QStringList& catelements)
379  {
380  // walk decrementally, and break once we fall back in the list of known categories
381  for (int kl = catelements.size()-1; kl >= 0; --kl) {
382  QString c = QStringList(catelements.mid(0,kl+1)).join("/");
383  if (pCatListCache.contains(c))
384  break;
385  pCatListCache.insert(qLowerBound(pCatListCache.begin(), pCatListCache.end(), c), c);
386  }
387  }
388 
389  bool pIsFetchingMore;
390 
391  int pLastSortPropId;
392  Qt::SortOrder pLastSortOrder;
393 
394  KLF_DEBUG_DECLARE_ASSIGNABLE_REF_INSTANCE() ;
395 };
396 
397 
398 
399 
400 
401 
402 
403 
404 // -----------------------------------------
405 
406 
409 {
410 public:
412  : pDView(dview), pViewType(dview->viewType())
413  {
414  }
415  virtual ~KLFLibDefViewCommon() { }
416 
417  // virtual void moveSelectedIconsBy(const QPoint& delta) = 0;
418 
420  virtual bool evDragEnter(QDragEnterEvent *de, const QPoint& pos) {
421  uint fl = pModel->dropFlags(de, thisView());
422  klfDbg( "KLFLibDefViewCommon::evDragEnter: drop flags are "<<fl<<"; this viewtype="<<pViewType ) ;
423  // decide whether to show drop indicator or not.
424  bool showdropindic = (fl & KLFLibModel::DropWillCategorize);
425  thisView()->setDropIndicatorShown(showdropindic);
426  // decide whether to accept the drop or to ignore it
428  // pViewType != IconView <= don't ignore if in icon view (where user can
429  // move the equations freely...by drag&drop)
430  de->ignore();
431  qDebug("Ignored drag enter event.");
432  } else {
434  de->accept();
435  klfDbg( "Accepted drag enter event issued at pos="<<pos ) ;
436  // and FAKE a QDragMoveEvent to the item view.
437  QDragEnterEvent fakeevent(de->pos(), de->dropAction(), de->mimeData(), de->mouseButtons(),
438  de->keyboardModifiers());
439  qApp->sendEvent(thisView()->viewport(), &fakeevent);
440  }
441  return true;
442  }
443 
445  virtual bool evDragMove(QDragMoveEvent *de, const QPoint& pos) {
446  uint fl = pModel->dropFlags(de, thisView());
447  klfDbg( "KLFLibDefViewCommon::evDragMove: flags are "<<fl<<"; pos is "<<pos ) ;
448  // decide whether to accept the drop or to ignore it
450  // pView != IconView <= don't ignore if in icon view (user can move the equations
451  // freely...by drag&drop)
452  de->ignore();
453  } else {
454  // check proposed actions
456  de->setDropAction(Qt::MoveAction);
457  } else {
458  de->setDropAction(Qt::CopyAction);
459  }
460  de->accept();
461  // and FAKE a QDragMoveEvent to the item view.
462  QDragMoveEvent fakeevent(de->pos(), de->dropAction(), de->mimeData(), de->mouseButtons(),
463  de->keyboardModifiers());
464  qApp->sendEvent(thisView()->viewport(), &fakeevent);
465  }
466  return true;
467  }
468 
470  virtual bool evDrop(QDropEvent *de, const QPoint& pos) {
471  if ( pViewType == KLFLibDefaultView::IconView && de->source() == thisView() ) {
472  // internal move -> send event directly
473  // qobject_cast<KLFLibDefListView*>(pView)->simulateEvent(event);
474  // qApp->sendEvent(object, event);
475  // move the objects ourselves because of bug (?) in Qt's handling?
476  QPoint delta = pos - mousePressedContentsPos;
477  klfDbg( "Delta is "<<delta ) ;
478  // and fake a QDragLeaveEvent
479  QDragLeaveEvent fakeevent;
480  qApp->sendEvent(thisView()->viewport(), &fakeevent);
481  // and manually move all selected indexes
482  // moveSelectedIconsBy(delta); .... IF we decide to sometime re-try supporting manual icon positioning...
483  thisView()->viewport()->update();
484  } else {
485  // and FAKE a QDropEvent to the item view.
486  klfDbg( "Drop event at position="<<de->pos() ) ;
487  QDropEvent fakeevent(de->pos(), de->dropAction(), de->mimeData(), de->mouseButtons(),
488  de->keyboardModifiers());
489  qApp->sendEvent(thisView()->viewport(), &fakeevent);
490  }
491  return true;
492  }
493 
494  virtual void commonStartDrag(Qt::DropActions supportedActions) {
495  // largely based on Qt's QAbstractItemView source in src/gui/itemviews/qabstractitemview.cpp
496  QModelIndexList indexes = commonSelectedIndexes();
497 
499  // icon view -> move icons around
500 
501  // this is not supported. This functionality was attempted and abandoned.
502  return;
503  }
504 
505  klfDbg( "Normal DRAG..." ) ;
506  /* // DEBUG:
507  if (indexes.count() > 0)
508  if (v->inherits("KLFLibDefListView")) {
509  klfDbg( "Got First index' rect: "
510  <<qobject_cast<KLFLibDefListView*>(v)->rectForIndex(indexes[0]) ) ;
511  qobject_cast<KLFLibDefListView*>(v)->setPositionForIndex(QPoint(200,100), indexes[0]);
512  }
513  */
514  if (indexes.count() == 0)
515  return;
516  QMimeData *data = pModel->mimeData(indexes);
517  if (data == NULL)
518  return;
519  QDrag *drag = new QDrag(thisView());
520  drag->setMimeData(data);
521  QPixmap pix = QPixmap::fromImage(pModel->dragImage(indexes));
522  drag->setPixmap(pix);
523  drag->setHotSpot(QPoint(0,0));
524  Qt::DropAction defaultDropAction = Qt::IgnoreAction;
525 
526  if (supportedActions & Qt::CopyAction &&
527  thisView()->dragDropMode() != QAbstractItemView::InternalMove)
528  defaultDropAction = Qt::CopyAction;
529 
530  drag->exec(supportedActions, defaultDropAction);
531  }
532 
533 
534  QModelIndex curVisibleIndex(bool firstOrLast) const {
535  Q_UNUSED(firstOrLast)
536 
537  // In the future, firstOrLast will be used to search forwards or backwards from the right point
538  klfDbg( "curVisibleIndex: offset y is "<<scrollOffset().y() ) ;
539  QModelIndex it = QModelIndex();
540  while ((it = pModel->walkNextIndex(it)).isValid()) {
541  klfDbg( "\texploring item it="<<it<<"; bottom="<<thisConstView()->visualRect(it).bottom() ) ;
542  if (thisConstView()->visualRect(it).bottom() >= 0) {
543  // first index from the beginning, that is after our scroll offset.
544  return it;
545  }
546  }
547  return pModel->walkNextIndex(QModelIndex());
548  /*
549  QModelIndex index;
550  QPoint offset = scrollOffset();
551  klfDbg( " offset="<<offset ) ;
552  int xStart, yStart;
553  int xStep, yStep;
554  if (firstOrLast) {
555  xStep = 40;
556  yStep = 40;
557  xStart = xStep/2;
558  yStart = yStep/2;
559  } else {
560  xStep = -40;
561  yStep = -40;
562  xStart = thisConstView()->width() - xStep/2;
563  yStart = thisConstView()->height() - yStep/2;
564  }
565  int xpos, ypos;
566  for (xpos = xStart; xpos > 0 && xpos < thisConstView()->width(); xpos += xStep) {
567  for (ypos = yStart; ypos > 0 && ypos < thisConstView()->height(); ypos += yStep) {
568  if ((index = thisConstView()->indexAt(QPoint(xpos,ypos))).isValid()) {
569  klfDbg( ": Found index = "<<index<<" at pos=("<<xpos<<","<<ypos<<"); "
570  <<" with offset "<<offset ) ;
571  return firstOrLast ? pModel->walkPrevIndex(index) : pModel->walkNextIndex(index);
572  }
573  }
574  }
575  return firstOrLast ? pModel->walkNextIndex(QModelIndex()) : pModel->walkPrevIndex(QModelIndex());
576  */
577  }
578 
579  virtual void modelInitialized() { }
580 
581 protected:
586 
587  virtual QModelIndexList commonSelectedIndexes() const = 0;
588  virtual void commonInternalDrag(Qt::DropActions a) = 0;
589  virtual QAbstractItemView *thisView() = 0;
590  virtual const QAbstractItemView *thisConstView() const = 0;
591  virtual QPoint scrollOffset() const = 0;
592 
594  virtual QPoint eventPos(QObject *object, QDragEnterEvent *event, int horoffset, int veroffset) {
595  if (object == thisView()->viewport())
596  return event->pos() + QPoint(horoffset, veroffset);
597  if (object == thisView())
598  return thisView()->viewport()->mapFromGlobal(thisView()->mapToGlobal(event->pos()))
599  + QPoint(horoffset, veroffset);
600  return event->pos() + QPoint(horoffset, veroffset);
601  }
602 
603  virtual bool setTheModel(QAbstractItemModel *m) {
604  KLFLibModel *model = qobject_cast<KLFLibModel*>(m);
605  if (model == NULL) {
606  qWarning()<<"KLFLibDefViewCommon::setTheModel: model is NULL or not a KLFLibModel :"<<model<<" !";
607  return false;
608  }
609  pModel = model;
610  return true;
611  }
612 
613  /* virtual void preparePaintEvent(QPaintEvent *e) */
614  /* { */
615  /* KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ; */
616  /* klfDbg("e->rect()="<<e->rect()); */
617  /* const QAbstractItemView *v = thisView(); */
618  /* QModelIndex idx; */
619  /* while ((idx = pModel->walkNextIndex(idx)).isValid()) { */
620  /* klfDbg("Testing for prefetching item at row="<<idx.row()<<" its rect="<<v->visualRect(idx)); */
621  /* if (e->rect().intersects(v->visualRect(idx))) { */
622  /* pModel->prefetch(QModelIndexList()<<idx); */
623  /* } */
624  /* } */
625  /* } */
626 
627 };
628 
629 
632 {
633  Q_OBJECT
634 public:
636  : QTreeView(parent), KLFLibDefViewCommon(parent), inPaintEvent(false), pInEventFilter(false)
637  {
638  installEventFilter(this);
639  viewport()->installEventFilter(this);
640  }
641 
642  virtual bool eventFilter(QObject *object, QEvent *event) {
643  if (pInEventFilter)
644  return QTreeView::eventFilter(object, event);
645  pInEventFilter = true;
646  bool eat = false;
647  if (event->type() == QEvent::DragEnter) {
648  eat = evDragEnter((QDragEnterEvent*)event, eventPos(object, (QDragEnterEvent*)event));
649  } else if (event->type() == QEvent::DragMove) {
650  eat = evDragMove((QDragMoveEvent*)event, eventPos(object, (QDragEnterEvent*)event));
651  } else if (event->type() == QEvent::Drop) {
652  eat = evDrop((QDropEvent*)event, eventPos(object, (QDragEnterEvent*)event));
653  }
654  // if (object == this && event->type() == QEvent::Paint)
655  // preparePaintEvent((QPaintEvent*)event);
656  pInEventFilter = false;
657  if (eat)
658  return eat;
659  return QTreeView::eventFilter(object, event);
660  }
661  virtual void setModel(QAbstractItemModel *model) {
662  if ( setTheModel(model) ) {
663  QTreeView::setModel(model);
664  }
665  }
666 
667 
668 public slots:
669 
670  virtual void selectAll() {
672  }
673 
674  void ensureExpandedTo(const QModelIndexList& mil)
675  {
676  int k;
677  for (k = 0; k < mil.size(); ++k) {
678  QModelIndex idx = mil[k];
679  if (!idx.isValid())
680  continue;
681  while (idx.parent().isValid()) {
682  klfDbg("expanding index "<<idx.parent()) ;
683  expand(idx.parent());
684  idx = idx.parent();
685  }
686  }
687  }
688 
689 
690 protected:
691  QModelIndexList commonSelectedIndexes() const { return selectedIndexes(); }
692  void commonInternalDrag(Qt::DropActions) { }
693  QAbstractItemView *thisView() { return this; }
694  const QAbstractItemView *thisConstView() const { return this; }
696 
699  }
700 
701  void startDrag(Qt::DropActions supportedActions) {
702  commonStartDrag(supportedActions);
703  }
704 
706  virtual void paintEvent(QPaintEvent *event) {
707  QTreeView::paintEvent(event);
708  }
709 
710  // reimpl. from QTreeView for debugging a segfault in fetchMore()
711  virtual void rowsInserted(const QModelIndex& parent, int start, int end)
712  {
714  QTreeView::rowsInserted(parent, start, end);
715  }
716 
718 };
719 
722 {
723  Q_OBJECT
724 public:
726  : QListView(parent), KLFLibDefViewCommon(parent), inPaintEvent(false), pInEventFilter(false),
727  pInitialLayoutDone(false), pWantRelayout(true)
728  {
729  installEventFilter(this);
730  viewport()->installEventFilter(this);
731  }
732 
733  virtual bool eventFilter(QObject *object, QEvent *event) {
734  if (pInEventFilter)
735  return false;
736  pInEventFilter = true;
737  bool eat = false;
738  if (event->type() == QEvent::DragEnter) {
739  eat = evDragEnter((QDragEnterEvent*)event, eventPos(object, (QDragEnterEvent*)event));
740  } else if (event->type() == QEvent::DragMove) {
741  eat = evDragMove((QDragMoveEvent*)event, eventPos(object, (QDragEnterEvent*)event));
742  } else if (event->type() == QEvent::Drop) {
743  eat = evDrop((QDropEvent*)event, eventPos(object, (QDragEnterEvent*)event));
744  }
745  // if (object == this && event->type() == QEvent::Paint)
746  // preparePaintEvent((QPaintEvent*)event);
747  pInEventFilter = false;
748  if (eat)
749  return eat;
750  return QListView::eventFilter(object, event);
751  }
752  virtual void setModel(QAbstractItemModel *model) {
753  if ( setTheModel(model) ) {
754  QListView::setModel(model);
755  }
756  }
757 
758 
759  void forceRelayout() {
760  scheduleDelayedItemsLayout(); // force a re-layout
761  }
762 
763  virtual void modelInitialized() {
764  klfDbg("scheduling an items layout...");
765  if (isVisible()) {
766  scheduleDelayedItemsLayout();
767  pInitialLayoutDone = true;
768  } else {
769  pInitialLayoutDone = false;
770  }
771  }
772 
773 protected:
774  virtual QModelIndexList commonSelectedIndexes() const { return selectedIndexes(); }
775  virtual void commonInternalDrag(Qt::DropActions a) { internalDrag(a); }
776  virtual QAbstractItemView *thisView() { return this; }
777  virtual const QAbstractItemView *thisConstView() const { return this; }
778  virtual QPoint scrollOffset() const { return QPoint(horizontalOffset(), verticalOffset()); }
779 
780  virtual QPoint eventPos(QObject *object, QDragEnterEvent *event) {
781  return KLFLibDefViewCommon::eventPos(object, event, horizontalOffset(), verticalOffset());
782  }
783 
785  virtual void paintEvent(QPaintEvent *event) {
786  QListView::paintEvent(event);
787  }
788 
791 
792  virtual void startDrag(Qt::DropActions supportedActions) {
793  commonStartDrag(supportedActions);
794  }
795 
796  virtual void showEvent(QShowEvent *event) {
797  if (!event->spontaneous()) {
798  klfDbg("Show event! initialLayoutDone="<<pInitialLayoutDone<<"; size hint="<<sizeHint());
799  if (!pInitialLayoutDone) {
800  scheduleDelayedItemsLayout();
801  pInitialLayoutDone = true;
802  }
803  }
804  QListView::showEvent(event);
805  }
806 
808 
809 };
810 
811 
812 
813 
814 
815 
816 
817 // ----------------------------------------------------------------------
818 
819 
820 
821 
822 
823 
824 
825 
826 
828 class KLFLibLocalFileOpenWidget : public QWidget, protected Ui::KLFLibLocalFileWidget
829 {
830  Q_OBJECT
831 
832  Q_PROPERTY(bool readyToOpen READ isReadyToOpen)
833 public:
835 
837  const QList<LocalFileType>& fileTypes)
838  : QWidget(parent)
839  {
840  pReadyToOpen = false;
841  pReadyToOpenUrl = QUrl();
842  pFileTypes = fileTypes;
843  setupUi(this);
844 
845  QStringList namefilters;
846  int k;
847  for (k = 0; k < pFileTypes.size(); ++k)
848  namefilters << pFileTypes[k].filepattern;
849  QDirModel *dirModel = new QDirModel(namefilters,
850  QDir::AllEntries|QDir::AllDirs|QDir::NoDotAndDotDot,
851  QDir::DirsFirst|QDir::IgnoreCase, this);
852 
853  QCompleter *fileNameCompleter = new QCompleter(this);
854  fileNameCompleter->setModel(dirModel);
855  txtFile->setCompleter(fileNameCompleter);
856 
857  setUrl(QUrl());
858  }
860 
861  virtual bool isReadyToOpen() const { return pReadyToOpen; }
862 
863  virtual QString selectedFName() const {
864  return QDir::fromNativeSeparators(txtFile->text());
865  }
866  virtual QString selectedScheme() const
867  {
868  QString filename = selectedFName();
869  LocalFileType ft = fileTypeForFileName(filename);
870  if (!ft.scheme.isEmpty())
871  return ft.scheme;
872  // fall back to guessing the scheme with the file contents
874  }
875 
877  {
878  QString fname = QFileInfo(filename).fileName();
879  int k;
880  for (k = 0; k < pFileTypes.size(); ++k) {
881  // test for this file type
882  QRegExp rgx(pFileTypes[k].filepattern, Qt::CaseInsensitive, QRegExp::Wildcard);
883  if (rgx.exactMatch(fname))
884  return pFileTypes[k];
885  }
886  if (!pFileTypes.size())
887  return LocalFileType();
888  return pFileTypes[0];
889  }
890 
891  virtual void setUrl(const QUrl& url) {
892  if (url.isValid() && url.path().length()>0)
893  txtFile->setText(QDir::toNativeSeparators(url.path()));
894  else
896  }
897  virtual QUrl url() const {
898  QString fname = selectedFName();
899  QString scheme = selectedScheme();
900  if (scheme.isEmpty())
901  return QUrl(); // invalid file type...
902 
903  QUrl url = QUrl::fromLocalFile(fname);
904  url.setScheme(scheme);
905  return url;
906  }
907 
908 signals:
909  void readyToOpen(bool ready);
910 
911 public slots:
912  void setReadyToOpen(bool ready, const QUrl& url) {
913  if (ready != pReadyToOpen || url != pReadyToOpenUrl) {
914  // ready to open state changes
915  pReadyToOpen = ready;
917  emit readyToOpen(ready);
918  }
919  }
920 
921 protected:
926 
927  virtual bool checkIsReadyToOpen(const QString& text = QString()) const
928  {
929  QString t = text.isNull() ? txtFile->text() : text;
930  return QFileInfo(t).isFile();
931  }
932 
933 
934 protected slots:
935  virtual bool browseFileName(BrowseType bt)
936  {
937  static QString selectedFilter;
938 
939  QString path = txtFile->text();
940  if (path.isEmpty())
942  QString pathfilter;
943  if (!QFileInfo(path).isDir()) {
944  LocalFileType pathft = fileTypeForFileName(path);
945  if (!pathft.filter.isEmpty())
946  pathfilter = pathft.filter;
947  }
948 
949  QStringList filters;
950  QStringList fpatterns;
951  int k;
952  int pathfilterN = -1;
953  for (k = 0; k < pFileTypes.size(); ++k) {
954  filters << pFileTypes[k].filter;
955  fpatterns << pFileTypes[k].filepattern;
956  if (pFileTypes[k].filter == pathfilter)
957  pathfilterN = k; // remember this one
958  }
959  if (bt == BrowseOpen) {
960  // only when opening
961  // NOTE: this doesn't work for save when we want to preserve 'path's extension, because
962  // Q(K?)FileDialog foolishly feels obliged to automatically force the first extension
963  // in the patterns list.
964  if (pathfilterN >= 0)
965  filters.removeAt(pathfilterN);
966  filters.prepend(tr("All Known Files (%1)").arg(fpatterns.join(" ")));
967  if (pathfilterN >= 0)
968  filters.prepend(pathfilter);
969  } else {
970  if (pathfilterN >= 0) {
971  filters.removeAt(pathfilterN);
972  filters.prepend(pathfilter);
973  }
974  }
975  filters.append(tr("All Files (*)"));
976  QString filter = filters.join(";;");
977  QString title = tr("Select Library Resource File");
978  QString name;
979  if (bt == BrowseOpen) {
980  name = QFileDialog::getOpenFileName(this, title, path, filter, &selectedFilter);
981  } else if (bt == BrowseSave) {
982  name = QFileDialog::getSaveFileName(this, title, path, filter, &selectedFilter);
983  } else {
984  qWarning()<<"KLFLibLocalFileOpenWidget::browseFileName: bad bt="<<bt;
985  name = QFileDialog::getSaveFileName(this, title, path, filter, &selectedFilter);
986  }
987  if ( name.isEmpty() )
988  return false;
989 
991 
992  txtFile->setText(name); // this will call on_txtFile_textChanged()
993  return true;
994  }
995  virtual void on_btnBrowse_clicked()
996  {
998  }
999  virtual void on_txtFile_textChanged(const QString& text)
1000  {
1002  }
1003 };
1004 
1005 // --------------------------------------
1006 
1009 {
1010  Q_OBJECT
1011 
1012  Q_PROPERTY(bool readyToCreate READ isReadyToCreate WRITE setReadyToCreate)
1013 public:
1015  const QList<LocalFileType>& fileTypes)
1016  : KLFLibLocalFileOpenWidget(parent, fileTypes)
1017  {
1018  pConfirmedOverwrite = false;
1019  pReadyToCreate = false;
1020  }
1022 
1023  QString fileName() const {
1024  return txtFile->text();
1025  }
1026 
1027  virtual bool isReadyToCreate() const { return pReadyToCreate; }
1028 
1029  virtual bool confirmedOverwrite() const { return pConfirmedOverwrite; }
1030 
1031 signals:
1032  void readyToCreate(bool ready);
1033 
1034 public slots:
1035  void setReadyToCreate(bool ready) {
1036  if (ready != pReadyToCreate) {
1037  pReadyToCreate = ready;
1039  }
1040  }
1041 
1042 protected slots:
1043  virtual void on_btnBrowse_clicked()
1044  {
1045  if ( browseFileName(BrowseSave) )
1046  pConfirmedOverwrite = true;
1047  }
1048  virtual void on_txtFile_textChanged(const QString& text)
1049  {
1050  pConfirmedOverwrite = false;
1051  setReadyToCreate(QFileInfo(text).absoluteDir().exists());
1052  }
1053 
1054 protected:
1057 };
1058 
1059 
1060 
1061 #ifdef KLF_DEBUG
1062 #include <QDebug>
1063 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::NodeId& n);
1064 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::Node& n);
1065 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::EntryNode& en);
1066 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::CategoryLabelNode& cn);
1067 #endif
1068 
1069 #endif
void setReadyToCreate(bool ready)
QDataStream & operator<<(QDataStream &stream, const KLFLatexSymbol &s)
bool searchNodeMatches(const NodeId &nodeId, const QString &searchString, Qt::CaseSensitivity cs)
virtual QPoint scrollOffset() const
Definition: klflibview_p.h:778
virtual bool eventFilter(QObject *object, QEvent *event)
Definition: klflibview_p.h:642
KLFLibModelSorter(KLFLibModelCache *c, KLFLibEntrySorter *es, bool groupcategories)
Definition: klflibview_p.h:295
setHotSpot(const QPoint &hotspot)
N takeNode(const NodeId &nid)
Definition: klflibview_p.h:191
toNativeSeparators(const QString &pathName)
virtual QModelIndexList commonSelectedIndexes() const
Definition: klflibview_p.h:774
Model for Item-Views displaying a library resource&#39;s contents.
Definition: klflibview.h:459
ignore(const QRect &rectangle)
virtual QAbstractItemView * thisView()
Definition: klflibview_p.h:776
virtual QImage dragImage(const QModelIndexList &indexes)
bool allChildrenFetched
TRUE if all the children of this node have been fetched and stored into children, FALSE if possibly t...
Definition: klflibview_p.h:132
KLFLibModel * pModel
Definition: klflibview_p.h:582
fromNativeSeparators(const QString &pathName)
QList< KLFLib::entryId > entryIdList(const QModelIndexList &indexlist)
KLFLibBasicWidgetFactory::LocalFileType LocalFileType
Definition: klflibview_p.h:834
A cached value of the size of value in Preview.
Definition: klflib.h:65
setMimeData(QMimeData *data)
KLFConfig klfconfig
Definition: klfconfig.cpp:88
qint32 entryId
An entry ID.
Definition: klflib.h:156
split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive)
void dumpNodeTree(NodeId node, int indent=0)
QPoint scrollOffset() const
Definition: klflibview_p.h:695
QString fullCategoryPath
The full category path of this category eg. &quot;Physics/General Relativity&quot;.
Definition: klflibview_p.h:156
QList< NodeId > children
Definition: klflibview_p.h:129
virtual void setModel(QAbstractItemModel *model)
Definition: klflibview_p.h:661
virtual ~KLFLibLocalFileOpenWidget()
Definition: klflibview_p.h:859
static const UIDType UIDIndexMask
Definition: klflibview_p.h:86
setPixmap(const QPixmap &pixmap)
QString categoryLabel
The last element in fullCategoryPath eg. &quot;General Relativity&quot;.
Definition: klflibview_p.h:154
void ensureNotMinimalist(NodeId nodeId, int count=-1)
Definition: klflibview.cpp:672
at(int i)
QAbstractItemView * thisView()
Definition: klflibview_p.h:693
virtual uint dropFlags(QDragMoveEvent *event, QAbstractItemView *view)
IndexType cacheFindCategoryLabel(QStringList catelements, bool createIfNotExists=false, bool notifyQtApi=false, bool newlyCreatedAreChildrenFetched=true)
setModel(QAbstractItemModel *model)
const QAbstractItemView * thisConstView() const
Definition: klflibview_p.h:694
contains(const QString &str, Qt::CaseSensitivity cs=Qt::CaseSensitive)
static NodeId rootNode()
Definition: klflibview_p.h:116
void ensureExpandedTo(const QModelIndexList &mil)
Definition: klflibview_p.h:674
#define klfDbg(streamableItems)
fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
virtual bool checkIsReadyToOpen(const QString &text=QString()) const
Definition: klflibview_p.h:927
int getNodeRow(NodeId nodeid)
Definition: klflibview.cpp:645
CategoryLabelNode & getCategoryLabelNodeRef(NodeId nodeid)
Definition: klflibview.cpp:635
join(const QString &separator)
void setReadyToOpen(bool ready, const QUrl &url)
Definition: klflibview_p.h:912
QList< KLFLib::entryId > entryIdForIndexList(const QModelIndexList &indexlist)
virtual void commonInternalDrag(Qt::DropActions a)=0
virtual void on_txtFile_textChanged(const QString &text)
bool canFetchMore(NodeId parentId)
Definition: klflibview.cpp:714
LocalFileType fileTypeForFileName(const QString &filename) const
Definition: klflibview_p.h:876
virtual QString selectedScheme() const
Definition: klflibview_p.h:866
virtual void modelInitialized()
Definition: klflibview_p.h:763
virtual void on_txtFile_textChanged(const QString &text)
Definition: klflibview_p.h:999
bool operator==(const NodeId &other) const
Definition: klflibview_p.h:100
virtual void commonStartDrag(Qt::DropActions supportedActions)
Definition: klflibview_p.h:494
The Latex Code of the equation.
Definition: klflib.h:62
static QList< int > minimalistEntryPropIds()
Definition: klflibview_p.h:246
void fetchMore(NodeId parentId, int batchCount=-1)
Definition: klflibview.cpp:735
KLFLibModel * pModel
Definition: klflibview_p.h:223
virtual void rowsInserted(const QModelIndex &parent, int start, int end)
Definition: klflibview_p.h:711
QString nodeValue(NodeId node, int propId=KLFLibEntry::Latex)
EntryNode(const EntryNode &copy)
Definition: klflibview_p.h:139
horizontalOffset()
virtual bool setTheModel(QAbstractItemModel *m)
Definition: klflibview_p.h:603
void sortCategory(NodeId category, KLFLibModelSorter *sorter, bool rootCall=true)
virtual bool isReadyToOpen() const
Definition: klflibview_p.h:861
QPoint mousePressedContentsPos
Definition: klflibview_p.h:585
append(const T &value)
NodeId(ItemKind k=ItemKind(EntryKind), IndexType i=-1)
Definition: klflibview_p.h:95
void unlinkNode(const NodeId &nid)
Definition: klflibview_p.h:183
QModelIndex createIndexFromId(NodeId nodeid, int row, int column)
Definition: klflibview.cpp:533
update(const QModelIndex &index)
accept(const QRect &rectangle)
void startDrag(Qt::DropActions supportedActions)
Definition: klflibview_p.h:701
NodeId nextNode(NodeId n)
NodeId prevNode(NodeId n)
KLFLibLocalFileCreateWidget(QWidget *parent, const QList< LocalFileType > &fileTypes)
Node(const Node &other)
Definition: klflibview_p.h:122
EntryNode & getEntryNodeRef(NodeId nodeid, bool requireNotMinimalist=false)
Definition: klflibview.cpp:621
void setSortingBy(int propId, Qt::SortOrder order)
Definition: klflibview_p.h:318
EntryNode pInvalidEntryNode
Definition: klflibview_p.h:208
virtual void paintEvent(QPaintEvent *event)
Definition: klflibview_p.h:706
rowsInserted(const QModelIndex &parent, int start, int end)
KLFLibModelCache(KLFLibModel *model)
Definition: klflibview_p.h:212
A known local file type for KLFLibBasicWidgetFactory-created widgets.
Definition: klflibview.h:1141
virtual QPoint eventPos(QObject *object, QDragEnterEvent *event)
Definition: klflibview_p.h:780
QModelIndex curVisibleIndex(bool firstOrLast) const
Definition: klflibview_p.h:534
NodeId getNodeForIndex(const QModelIndex &index)
Definition: klflibview.cpp:568
virtual bool evDragEnter(QDragEnterEvent *de, const QPoint &pos)
Definition: klflibview_p.h:420
setScheme(const QString &scheme)
virtual void showEvent(QShowEvent *event)
Definition: klflibview_p.h:796
bool isAllocated(IndexType i)
Definition: klflibview_p.h:164
void treeInsertEntry(const EntryNode &e, bool isRebuildingCache=false)
Definition: klflibview.cpp:963
KLFLibDefaultView * pDView
Definition: klflibview_p.h:583
static const quint8 UIDKindShift
Definition: klflibview_p.h:84
bool allocated
Whether this node is used. when false, this Node object is just unused memory space in the cache list...
Definition: klflibview_p.h:126
virtual const QAbstractItemView * thisConstView() const
Definition: klflibview_p.h:777
The Category to which eq. belongs (path-style string)
Definition: klflib.h:66
virtual bool evDragMove(QDragMoveEvent *de, const QPoint &pos)
Definition: klflibview_p.h:445
UIDType universalId() const
Definition: klflibview_p.h:106
virtual void selectAll()
Definition: klflibview_p.h:670
#define KLF_DEBUG_TIME_BLOCK(msg)
QModelIndexList commonSelectedIndexes() const
Definition: klflibview_p.h:691
QList< LocalFileType > pFileTypes
Definition: klflibview_p.h:922
#define KLF_FUNC_NAME
virtual QModelIndexList commonSelectedIndexes() const =0
Tags about the equation (string)
Definition: klflib.h:67
virtual QPoint eventPos(QObject *object, QDragEnterEvent *event, int horoffset, int veroffset)
Definition: klflibview_p.h:594
virtual ~KLFLibModelCache()
Definition: klflibview_p.h:221
static QString guessLocalFileScheme(const QString &fileName)
QPointF sizeToPointF(const QSizeF &s)
Definition: klflibview_p.h:63
virtual const QAbstractItemView * thisConstView() const =0
virtual void setModel(QAbstractItemModel *model)
Definition: klflibview_p.h:752
virtual void commonInternalDrag(Qt::DropActions a)
Definition: klflibview_p.h:775
void commonInternalDrag(Qt::DropActions)
Definition: klflibview_p.h:692
virtual QString selectedFName() const
Definition: klflibview_p.h:863
bool operator!=(const NodeId &other) const
Definition: klflibview_p.h:103
virtual void on_btnBrowse_clicked()
Definition: klflibview_p.h:995
QModelIndexList findEntryIdList(const QList< KLFLib::entryId > &eidlist)
KLFLibDefViewCommon(KLFLibDefaultView *dview)
Definition: klflibview_p.h:411
NodeId lastNode(NodeId n)
isValid()
QString filter
eg. &quot;Local Library Database File (*.klf.db)&quot;
Definition: klflibview.h:1144
QString lastFileDialogPath
Definition: klfconfig.h:244
virtual void on_btnBrowse_clicked()
KLFLibDefListView(KLFLibDefaultView *parent)
Definition: klflibview_p.h:725
QStringList categoryListCache()
Definition: klflibview_p.h:359
An entry (single formula) in the library.
Definition: klflib.h:55
Node & getNodeRef(NodeId nodeid)
Definition: klflibview.cpp:598
void unlinkNode(IndexType index)
Definition: klflibview_p.h:184
virtual bool isReadyToCreate() const
KLFLibDefTreeView(KLFLibDefaultView *parent)
Definition: klflibview_p.h:635
virtual void modelInitialized()
Definition: klflibview_p.h:579
getSaveFileName(QWidget *parent=0, const QString &caption=QString()
virtual QAbstractItemView * thisView()=0
virtual QMimeData * mimeData(const QModelIndexList &indexes) const
virtual void setUrl(const QUrl &url)
Definition: klflibview_p.h:891
virtual QUrl url() const
Definition: klflibview_p.h:897
static const UIDType UIDInvalid
Definition: klflibview_p.h:87
virtual QPoint scrollOffset() const =0
Node getNode(NodeId nodeid)
Definition: klflibview.cpp:591
virtual bool evDrop(QDropEvent *de, const QPoint &pos)
Definition: klflibview_p.h:470
CategoryLabelNode(const CategoryLabelNode &copy)
Definition: klflibview_p.h:151
QString scheme
eg. &quot;klf+sqlite&quot;
Definition: klflibview.h:1142
KLFLibEntrySorter * entrySorter()
Definition: klflibview_p.h:302
QSizeF pointToSizeF(const QPointF &p)
Definition: klflibview_p.h:65
static const UIDType UIDKindMask
Definition: klflibview_p.h:85
Utility class for sorting library entry items.
Definition: klflib.h:276
QPoint eventPos(QObject *object, QDragEnterEvent *event)
Definition: klflibview_p.h:697
getOpenFileName(QWidget *parent=0, const QString &caption=QString()
virtual ~KLFLibDefViewCommon()
Definition: klflibview_p.h:415
expand(const QModelIndex &index)
virtual bool eventFilter(QObject *object, QEvent *event)
Definition: klflibview_p.h:733
virtual void slotSelectAll(bool expandItems=false)
virtual QModelIndex walkNextIndex(const QModelIndex &cur)
Call repeatedly to walk all indexes (once each exactly, first column only)
NodeCache< EntryNode > EntryCache
Definition: klflibview_p.h:205
The Date/Time at which the equation was evaluated.
Definition: klflib.h:63
struct KLFConfig::@4 LibraryBrowser
static NodeId fromUID(UIDType uid)
Definition: klflibview_p.h:113
virtual void paintEvent(QPaintEvent *event)
Definition: klflibview_p.h:785
void updateData(const QList< KLFLib::entryId > &entryIdList, int modifyType)
Definition: klflibview.cpp:840
virtual bool browseFileName(BrowseType bt)
Definition: klflibview_p.h:935
exactMatch(const QString &str)
IndexType insertNewNode(const N &n)
Definition: klflibview_p.h:166
virtual bool confirmedOverwrite() const
virtual void startDrag(Qt::DropActions supportedActions)
Definition: klflibview_p.h:792
EntryNode treeTakeEntry(const NodeId &e, bool notifyQtApi=true)
NodeId findEntryId(KLFLib::entryId eId)
KLFLibLocalFileOpenWidget(QWidget *parent, const QList< LocalFileType > &fileTypes)
Definition: klflibview_p.h:836
operator[](int i)
KLFLibDefaultView::ViewType pViewType
Definition: klflibview_p.h:584
fromLocalFile(const QString &localFile)
N takeNode(IndexType index)
Definition: klflibview_p.h:192
NodeCache< CategoryLabelNode > CategoryLabelCache
Definition: klflibview_p.h:206

Generated by doxygen 1.8.5