[KLF Backend][KLF Tools][KLF Home]
KLatexFormula Project
src/klftools/klfitemviewsearchtarget.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002  *   file klfitemviewsearchtarget.cpp
00003  *   This file is part of the KLatexFormula Project.
00004  *   Copyright (C) 2012 by Philippe Faist
00005  *   philippe.faist at bluewin.ch
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 /* $Id$ */
00023 
00024 #include <QList>
00025 #include <QMap>
00026 #include <QAbstractItemView>
00027 #include <QAbstractItemModel>
00028 
00029 #include "klfitemviewsearchtarget.h"
00030 #include "klfitemviewsearchtarget_p.h"
00031 
00032 
00033 struct KLFItemViewSearchTargetPrivate {
00034   KLF_PRIVATE_HEAD(KLFItemViewSearchTarget)
00035   {
00036     view = NULL;
00037     olddelegate = NULL;
00038     klfdelegate = new KLFSearchItemDelegate(K);
00039   }
00040 
00041   QAbstractItemView * view;
00042 
00043   QAbstractItemDelegate * olddelegate;
00044   KLFSearchItemDelegate * klfdelegate;
00045 
00046   void resetDelegate();
00047 
00048   QList<int> columnlist;
00049   QMap<int,int> nextcolumn;
00050   QMap<int,int> prevcolumn;
00051 
00052   int next_valid_column(int c, bool forward = true)
00053   {
00054     if (columnlist.isEmpty())
00055       return -1;
00056 
00057     while (c >= 0 && c < columnlist.last() && !columnlist.contains(c))
00058       c = c + (forward ? +1 : -1);
00059     if (c >= columnlist.last())
00060       c = -1;
00061     return c;
00062   }
00063 
00064   QModelIndex advance_iter_helper(const QModelIndex& pos, bool explorechildren = true)
00065   {
00066     KLF_ASSERT_NOT_NULL(view, "View is NULL!", return QModelIndex(); );
00067     QAbstractItemModel *model = view->model();
00068     KLF_ASSERT_NOT_NULL(model, "View's model is NULL!", return QModelIndex(); );
00069     
00070     if (columnlist.isEmpty())
00071       return QModelIndex();
00072 
00073     if (explorechildren && model->hasChildren(pos)) {
00074       // explore children
00075       return model->index(0, columnlist[0], pos);
00076     }
00077     // no children, move to next column
00078     int nextcol = nextcolumn.value(next_valid_column(pos.column()), -1);
00079     if (nextcol >= 0) {
00080       // valid next column to move to
00081       return model->index(pos.row(), nextcol, pos.parent());
00082     }
00083     // we're at last column, try next row
00084     if (pos.row() < model->rowCount(pos.parent())) {
00085       return pos.sibling(pos.row()+1, columnlist[0]);
00086     }
00087     // otherwise, we're at the end of (sub-?)list
00088     // try parent
00089     if (pos.parent() != QModelIndex()) {
00090       return advance_iter_helper(pos.parent(), false); // don't re-iterate to children...
00091     }
00092     // we seem to be at the end of the list...
00093     return QModelIndex();
00094   }
00095 
00096   QModelIndex last_child_index(const QModelIndex& pos)
00097   {
00098     KLF_ASSERT_NOT_NULL(view, "View is NULL!", return QModelIndex(); );
00099     QAbstractItemModel *model = view->model();
00100     KLF_ASSERT_NOT_NULL(model, "View's model is NULL!", return QModelIndex(); );
00101     
00102     if (!model->hasChildren(pos))
00103       return pos;
00104 
00105     // children: return last node of last child.
00106     return last_child_index(model->index(model->rowCount(pos)-1, columnlist.last(), pos));
00107   }
00108 
00109   QModelIndex advance_iter_back_helper(const QModelIndex& pos)
00110   {
00111     KLF_ASSERT_NOT_NULL(view, "View is NULL!", return QModelIndex(); );
00112     QAbstractItemModel *model = view->model();
00113     KLF_ASSERT_NOT_NULL(model, "View's model is NULL!", return QModelIndex(); );
00114 
00115     // try to go to previous column
00116     int prevcol = prevcolumn.value(next_valid_column(pos.column(), false), -1);
00117     if (prevcol >= 0) {
00118       return last_child_index(pos.sibling(pos.row(), prevcol));
00119     }
00120     if (pos.row() >= 1) {
00121       // there is a previous sibling
00122       return last_child_index(pos.sibling(pos.row()-1, columnlist.last()));
00123     }
00124     // there is no previous sibling: so we can return the parent
00125     return pos.parent();
00126   }
00127 };
00128 
00129 
00130 KLFItemViewSearchTarget::KLFItemViewSearchTarget(QAbstractItemView *view, QObject *parent)
00131   : QObject(parent), KLFIteratorSearchable<QModelIndex>()
00132 {
00133   KLF_INIT_PRIVATE(KLFItemViewSearchTarget) ;
00134   setSearchView(view);
00135 }
00136 KLFItemViewSearchTarget::~KLFItemViewSearchTarget()
00137 {
00138   KLF_DELETE_PRIVATE ;
00139 }
00140 
00141 
00142 QAbstractItemView * KLFItemViewSearchTarget::view()
00143 {
00144   return d->view;
00145 }
00146 QList<int> KLFItemViewSearchTarget::searchColumns()
00147 {
00148   return d->columnlist;
00149 }
00150 
00151 
00152 
00153 
00154 QModelIndex KLFItemViewSearchTarget::searchIterAdvance(const QModelIndex& pos, bool forward)
00155 {
00156   if (forward)
00157     return d->advance_iter_helper(pos);
00158   // backwards search
00159   return d->advance_iter_back_helper(pos);
00160 }
00161 QModelIndex KLFItemViewSearchTarget::searchIterBegin()
00162 {
00163   return d->advance_iter_helper(QModelIndex());
00164 }
00165 QModelIndex KLFItemViewSearchTarget::searchIterEnd()
00166 {
00167   return QModelIndex();
00168 }
00169 bool KLFItemViewSearchTarget::searchIterMatches(const QModelIndex &pos, const QString &queryString)
00170 {
00171   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00172 
00173   QList<KLFSearchItemDelegate::Match> mlist
00174     = KLFSearchItemDelegate::matches(pos.data().toString(), queryString, false);
00175   return mlist.size();
00176 }
00177 void KLFItemViewSearchTarget::searchPerformed(const QModelIndex& resultMatchPosition, bool found,
00178                                               const QString& queryString)
00179 {
00180   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00181 
00182   Q_UNUSED(resultMatchPosition);
00183   Q_UNUSED(found);
00184 
00185   // WARNING: If item properties are set in the model itself then this is seen by views/delegates as edits!
00186   //    KLF_ASSERT_NOT_NULL(d->view, "View is NULL!", return ; );
00187   //    QAbstractItemModel * model = d->view->model();
00188   //    KLF_ASSERT_NOT_NULL(model, "View has NULL model!!!", return ; ) ;
00189   //    model->setData(resultMatchPosition, QColor(128,255,255,128), Qt::BackgroundRole);
00190 
00191   KLF_ASSERT_NOT_NULL(d->view, "View is NULL!", return ; );
00192   QAbstractItemDelegate *delegate = d->view->itemDelegate();
00193   KLF_ASSERT_NOT_NULL(delegate, "Delegate is NULL!", return ; );
00194   if (delegate != d->klfdelegate) {
00195     d->olddelegate = delegate;
00196     d->view->setItemDelegate(d->klfdelegate);
00197   }
00198 
00199   d->klfdelegate->setSearchString(queryString);
00200   d->view->repaint();
00201 }
00202 void KLFItemViewSearchTargetPrivate::resetDelegate()
00203 {
00204   KLF_ASSERT_NOT_NULL(view, "View is NULL!", return ; );
00205   QAbstractItemDelegate *delegate = view->itemDelegate();
00206   KLF_ASSERT_NOT_NULL(delegate, "Delegate is NULL!", return ; );
00207   if (delegate == klfdelegate && olddelegate != NULL) {
00208     view->setItemDelegate(olddelegate);
00209   }
00210   view->repaint();
00211 }
00212 void KLFItemViewSearchTarget::searchAborted()
00213 {
00214   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00215   KLFIteratorSearchable<QModelIndex>::searchAborted();
00216 
00217   d->resetDelegate();
00218 }
00219 void KLFItemViewSearchTarget::searchReinitialized()
00220 {
00221   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00222   KLFIteratorSearchable<QModelIndex>::searchReinitialized();
00223 
00224   d->resetDelegate();
00225 }
00226 
00227 void KLFItemViewSearchTarget::searchMoveToIterPos(const QModelIndex& pos)
00228 {
00229   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00230 
00231   KLF_ASSERT_NOT_NULL(d->view, "View is NULL!", return ; );
00232   d->view->setCurrentIndex(pos);
00233   d->view->selectionModel()->select(pos, QItemSelectionModel::ClearAndSelect);
00234 }
00235 
00236 void KLFItemViewSearchTarget::setSearchView(QAbstractItemView *view)
00237 {
00238   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00239 
00240   d->view = view;
00241 
00242   if (d->columnlist.isEmpty()) {
00243     // empty list means all columns
00244     setSearchColumns(QList<int>());
00245   }
00246 }
00247 
00248 void KLFItemViewSearchTarget::setSearchColumns(const QList<int>& columnList)
00249 {
00250   KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00251 
00252   KLF_ASSERT_NOT_NULL(d->view, "View is NULL!", return ; );
00253   QAbstractItemModel * model = d->view->model();
00254   KLF_ASSERT_NOT_NULL(model, "View has NULL model!!!", return ; ) ;
00255 
00256   // set-list conversion to remove duplicates, and sorted so it's nice :)
00257   d->columnlist = columnList.toSet().toList();
00258   qSort(d->columnlist);
00259   d->nextcolumn.clear();
00260   d->prevcolumn.clear();
00261   if (d->columnlist.isEmpty()) {
00262     for (int k = 0; k < model->columnCount(); ++k)
00263       d->columnlist << k;
00264   }
00265   if (d->columnlist.isEmpty()) // model has no columns, don't insist
00266     return;
00267   int k;
00268 
00269   for (k = 0; k < (d->columnlist.size()-1); ++k) {
00270     d->nextcolumn[d->columnlist[k]] = d->columnlist[k+1];
00271     d->prevcolumn[d->columnlist[k+1]] = d->columnlist[k];
00272   }
00273   d->nextcolumn[d->columnlist[k]] = -1;
00274   d->prevcolumn[d->columnlist[0]] = -1;
00275 }
00276 
00277 
00278 

Generated by doxygen 1.7.6.1. The KLatexFormula website is hosted on sourceforge.net