• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Kate

katecompletiontree.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2006 Hamish Rodda <rodda@kde.org>
00003    Copyright (C) 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License version 2 as published by the Free Software Foundation.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "katecompletiontree.h"
00021 
00022 #include <QtGui/QHeaderView>
00023 #include <QtGui/QScrollBar>
00024 #include <QVector>
00025 #include <QTimer>
00026 #include <QApplication>
00027 #include <QDesktopWidget>
00028 
00029 #include "kateview.h"
00030 #include "katerenderer.h"
00031 #include "kateconfig.h"
00032 
00033 #include "katecompletionwidget.h"
00034 #include "katecompletiondelegate.h"
00035 #include "katecompletionmodel.h"
00036 
00037 KateCompletionTree::KateCompletionTree(KateCompletionWidget* parent)
00038   : ExpandingTree(parent)
00039 {
00040   header()->hide();
00041   setRootIsDecorated(false);
00042   setIndentation(0);
00043   setFrameStyle(QFrame::NoFrame);
00044   setAllColumnsShowFocus(true);
00045   setAlternatingRowColors(true);
00046   //We need ScrollPerItem, because ScrollPerPixel is too slow with a very large competion-list(see KDevelop).
00047   setVerticalScrollMode(QAbstractItemView::ScrollPerItem);
00048 
00049   m_resizeTimer = new QTimer(this);
00050   m_resizeTimer->setSingleShot(true);
00051 
00052   connect(m_resizeTimer, SIGNAL(timeout()), this, SLOT(resizeColumnsSlot()));
00053   
00054   // Provide custom highlighting to completion entries
00055   setItemDelegate(new KateCompletionDelegate(widget()->model(), widget()));
00056   
00058   //connect(widget()->model(), SIGNAL(contentGeometryChanged()), this, SLOT(resizeColumnsSlot()));
00059 
00060   // Prevent user from expanding / collapsing with the mouse
00061   setItemsExpandable(false);
00062   setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00063 }
00064 
00065 void KateCompletionTree::currentChanged ( const QModelIndex & current, const QModelIndex & previous ) {
00066   widget()->model()->rowSelected(current);
00067   ExpandingTree::currentChanged(current, previous);
00068 }
00069 
00070 void KateCompletionTree::scrollContentsBy( int dx, int dy )
00071 {
00072   QTreeView::scrollContentsBy(dx, dy);
00073 
00074   if (isVisible())
00075     m_resizeTimer->start(300);
00076 }
00077 
00078 KateCompletionWidget * KateCompletionTree::widget( ) const
00079 {
00080   return static_cast<KateCompletionWidget*>(const_cast<QObject*>(parent()));
00081 }
00082 
00083 void KateCompletionTree::resizeColumnsSlot()
00084 {
00085   if(model())
00086     resizeColumns();
00087 }
00088 
00089 void KateCompletionTree::resizeColumns(bool fromResizeEvent, bool firstShow, bool forceResize)
00090 {
00091   static bool preventRecursion = false;
00092   if (preventRecursion)
00093     return;
00094   
00095   if(firstShow)
00096     forceResize = true;
00097 
00098   preventRecursion = true;
00099 
00100   widget()->setUpdatesEnabled(false);
00101 
00102   int modelIndexOfName = kateModel()->translateColumn(KTextEditor::CodeCompletionModel::Name);
00103   int oldIndentWidth = columnViewportPosition(modelIndexOfName);
00104 
00106 
00107   int numColumns = model()->columnCount();
00108   
00109   QVector<int> columnSize(numColumns, 5);
00110 
00111   uint currentYPos = 0;
00112 
00113   QModelIndex current = indexAt(QPoint(1,1));
00114   if( current.child(0,0).isValid() ) { //If the index has children, it is a group-label. Then we should start with it's first child.
00115     currentYPos += sizeHintForIndex(current).height();
00116     current = current.child(0,0);
00117   }
00118 
00119   int num = 0;
00120   bool changed = false;
00121   
00122   while( current.isValid() && currentYPos < height() )
00123   {
00124 //     kDebug() << current.row() << "out of" << model()->rowCount(current.parent()) << "in" << current.parent().data(Qt::DisplayRole);
00125     currentYPos += sizeHintForIndex(current).height();
00126 //     itemDelegate()->sizeHint(QStyleOptionViewItem(), current).isValid() && itemDelegate()->sizeHint(QStyleOptionViewItem(), current).intersects(visibleViewportRect)
00127     changed = true;
00128     num++;
00129     for( int a = 0; a < numColumns; a++ )
00130     {
00131       QSize s = sizeHintForIndex (current.sibling(current.row(), a));
00132 //       kDebug() << "size-hint for" << current.row() << a << ":" << s << current.sibling(current.row(), a).data(Qt::DisplayRole);
00133       if( s.width() > columnSize[a] && s.width() < 2000 )
00134         columnSize[a] = s.width();
00135       else if( s.width() > 2000 )
00136         kDebug( 13035 ) << "got invalid size-hint of width " << s.width();
00137     }
00138 
00139     QModelIndex oldCurrent = current;
00140     current = current.sibling(current.row()+1, 0);
00141     
00142     //Are we at the end of a group? If yes, move on into the next group
00143     if( !current.isValid() && oldCurrent.parent().isValid() ) {
00144       current = oldCurrent.parent().sibling( oldCurrent.parent().row()+1, 0 );
00145       if( current.isValid() && current.child(0,0).isValid() ) {
00146     currentYPos += sizeHintForIndex(current).height();
00147         current = current.child(0,0);
00148       }
00149     }
00150   }
00151 
00152   int totalColumnsWidth = 0, originalViewportWidth = viewport()->width();
00153   
00154   int maxWidth = (QApplication::desktop()->screenGeometry(widget()->view()).width()*3) / 4;
00155 
00157   //This contains several hacks to reduce the amount of resizing that happens. Generally,
00158   //resizes only happen if a) More than a specific amount of space is saved by the resize, or
00159   //b) the resizing is required so the list can show all of its contents.
00160   int minimumResize = 0;
00161   int maximumResize = 0;
00162   
00163   if( changed ) {
00164 
00165     for( int n = 0; n < numColumns; n++ ) {
00166       totalColumnsWidth += columnSize[n];
00167       
00168       int diff = columnSize[n] - columnWidth(n);
00169       if( diff < minimumResize )
00170         minimumResize = diff;
00171       if( diff > maximumResize )
00172         maximumResize = diff;
00173     }
00174     
00175     int noReduceTotalWidth = 0; //The total width of the widget of no columns are reduced
00176     for( int n = 0; n < numColumns; n++ ) {
00177       if(columnSize[n] < columnWidth(n))
00178         noReduceTotalWidth += columnWidth(n);
00179       else
00180         noReduceTotalWidth += columnSize[n];
00181     }
00182 
00183     //Check whether we can afford to reduce none of the columns
00184     //Only reduce size if we widget would else be too wide.
00185   bool noReduce = noReduceTotalWidth < maxWidth && !forceResize;
00186 
00187     if(noReduce) {
00188       totalColumnsWidth = 0;
00189       for( int n = 0; n < numColumns; n++ ) {
00190         if(columnSize[n] < columnWidth(n))
00191           columnSize[n] = columnWidth(n);
00192 
00193         totalColumnsWidth += columnSize[n];
00194       }
00195     }
00196 
00197     if( minimumResize > -40 && maximumResize == 0 && !forceResize ) {
00198       //No column needs to be exanded, and no column needs to be reduced by more than 40 pixels.
00199       //To prevent flashing, do not resize at all.
00200       totalColumnsWidth = 0;
00201       for( int n = 0; n < numColumns; n++ ) {
00202         columnSize[n] = columnWidth(n);
00203         totalColumnsWidth += columnSize[n];
00204       }
00205     } else {
00206 //       viewport()->resize( 5000, viewport()->height() );
00207       for( int n = 0; n < numColumns; n++ ) {
00208         setColumnWidth(n, columnSize[n]);
00209       }
00210 //       kDebug() << "resizing viewport to" << totalColumnsWidth;
00211       viewport()->resize( totalColumnsWidth, viewport()->height() );
00212     }
00213   }
00214 
00216   
00217   int scrollBarWidth = verticalScrollBar()->width();
00218   
00219   int newIndentWidth = columnViewportPosition(modelIndexOfName);
00220 
00221   int newWidth = qMin(maxWidth, qMax(75, totalColumnsWidth));
00222   
00223   if(newWidth == maxWidth)
00224     setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
00225   else
00226     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00227     
00228   if(maximumResize > 0 || forceResize || oldIndentWidth != newIndentWidth) {
00229   
00230     //   kDebug() << geometry() << "newWidth" << newWidth << "current width" << width() << "target width" << newWidth + scrollBarWidth;
00231     
00232     if((newWidth + scrollBarWidth) != width() && originalViewportWidth != totalColumnsWidth)
00233     {
00234         widget()->resize(newWidth + scrollBarWidth + 2, widget()->height());
00235         resize(newWidth + scrollBarWidth, widget()->height()- (2*widget()->frameWidth()));
00236     }
00237     
00238     //   kDebug() << "created geometry:" << widget()->geometry() << geometry() << "newWidth" << newWidth << "viewport" << viewport()->width();
00239     
00240     if( viewport()->width() > totalColumnsWidth ) //Set the size of the last column to fill the whole rest of the widget
00241     setColumnWidth(numColumns-1, viewport()->width() - columnViewportPosition(numColumns-1));
00242     
00243     /*  for(int a = 0; a < numColumns; ++a)
00244         kDebug() << "column" << a << columnWidth(a) << "target:" << columnSize[a];*/
00245     
00246     if (oldIndentWidth != newIndentWidth)
00247         if(widget()->updatePosition() && !forceResize) {
00248         preventRecursion = false;
00249         resizeColumns(false, true, true);
00250         }
00251   }
00252     
00253   widget()->setUpdatesEnabled(true);
00254   
00255   preventRecursion = false;
00256 }
00257 
00258 QStyleOptionViewItem KateCompletionTree::viewOptions( ) const
00259 {
00260   QStyleOptionViewItem opt = QTreeView::viewOptions();
00261 
00262   opt.font = widget()->view()->renderer()->config()->font();
00263 
00264   return opt;
00265 }
00266 
00267 KateCompletionModel * KateCompletionTree::kateModel( ) const
00268 {
00269   return static_cast<KateCompletionModel*>(model());
00270 }
00271 
00272 bool KateCompletionTree::nextCompletion()
00273 {
00274   QModelIndex current;
00275   QModelIndex firstCurrent = currentIndex();
00276 
00277   do {
00278     QModelIndex oldCurrent = currentIndex();
00279 
00280     current = moveCursor(MoveDown, Qt::NoModifier);
00281 
00282     if (current != oldCurrent && current.isValid()) {
00283       setCurrentIndex(current);
00284     } else {
00285       if (firstCurrent.isValid())
00286         setCurrentIndex(firstCurrent);
00287       return false;
00288     }
00289 
00290   } while (!kateModel()->indexIsItem(current));
00291 
00292   return true;
00293 }
00294 
00295 bool KateCompletionTree::previousCompletion()
00296 {
00297   QModelIndex current;
00298   QModelIndex firstCurrent = currentIndex();
00299 
00300   do {
00301     QModelIndex oldCurrent = currentIndex();
00302 
00303     current = moveCursor(MoveUp, Qt::NoModifier);
00304 
00305     if (current != oldCurrent && current.isValid()) {
00306       setCurrentIndex(current);
00307 
00308     } else {
00309       if (firstCurrent.isValid())
00310         setCurrentIndex(firstCurrent);
00311       return false;
00312     }
00313 
00314   } while (!kateModel()->indexIsItem(current));
00315 
00316   return true;
00317 }
00318 
00319 bool KateCompletionTree::pageDown( )
00320 {
00321   QModelIndex old = currentIndex();
00322   
00323   QModelIndex current = moveCursor(MovePageDown, Qt::NoModifier);
00324 
00325   if (current.isValid()) {
00326     setCurrentIndex(current);
00327     if (!kateModel()->indexIsItem(current))
00328       if (!nextCompletion())
00329         previousCompletion();
00330   }
00331 
00332   return current != old;
00333 }
00334 
00335 bool KateCompletionTree::pageUp( )
00336 {
00337   QModelIndex old = currentIndex();
00338   QModelIndex current = moveCursor(MovePageUp, Qt::NoModifier);
00339 
00340   if (current.isValid()) {
00341     setCurrentIndex(current);
00342     if (!kateModel()->indexIsItem(current))
00343       if (!previousCompletion())
00344         nextCompletion();
00345   }
00346   return current != old;
00347 }
00348 
00349 void KateCompletionTree::top( )
00350 {
00351   QModelIndex current = moveCursor(MoveHome, Qt::NoModifier);
00352   setCurrentIndex(current);
00353 
00354   if (current.isValid()) {
00355     setCurrentIndex(current);
00356     if (!kateModel()->indexIsItem(current))
00357       nextCompletion();
00358   }
00359 }
00360 
00361 void KateCompletionTree::scheduleUpdate()
00362 {
00363     m_resizeTimer->start(300);
00364 }
00365 
00366 void KateCompletionTree::bottom( )
00367 {
00368   QModelIndex current = moveCursor(MoveEnd, Qt::NoModifier);
00369   setCurrentIndex(current);
00370 
00371   if (current.isValid()) {
00372     setCurrentIndex(current);
00373     if (!kateModel()->indexIsItem(current))
00374       previousCompletion();
00375   }
00376 }
00377 
00378 #include "katecompletiontree.moc"

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal