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