kate Library API Documentation

katefilelist.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
00003    Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
00004    Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License version 2 as published by the Free Software Foundation.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 //BEGIN Includes
00022 #include "katefilelist.h"
00023 #include "katefilelist.moc"
00024 
00025 #include "katedocmanager.h"
00026 #include "kateviewmanager.h"
00027 #include "katemainwindow.h"
00028 
00029 #include <qapplication.h>
00030 #include <qpainter.h>
00031 #include <qpopupmenu.h>
00032 #include <qheader.h>
00033 #include <qcolor.h>
00034 #include <qcheckbox.h>
00035 #include <qlayout.h>
00036 #include <qgroupbox.h>
00037 #include <qlabel.h>
00038 #include <qwhatsthis.h>
00039 
00040 #include <kiconloader.h>
00041 #include <kconfig.h>
00042 #include <klocale.h>
00043 #include <kglobalsettings.h>
00044 #include <kpassivepopup.h>
00045 #include <kdebug.h>
00046 #include <kapplication.h>
00047 #include <kstringhandler.h>
00048 #include <kcolorbutton.h>
00049 #include <kdialog.h>
00050 //END Includes
00051 
00052 //BEGIN ToolTip
00053 class ToolTip : public QToolTip
00054 {
00055   public:
00056     ToolTip( QWidget *parent, KateFileList *lv )
00057       : QToolTip( parent ),
00058     m_listView( lv )
00059     {
00060     }
00061     virtual ~ToolTip() {};
00062 
00063     void maybeTip( const QPoint &pos )
00064     {
00065       QListViewItem *i = m_listView->itemAt( pos );
00066       if ( ! i ) return;
00067 
00068       KateFileListItem *item = ((KateFileListItem*)i);
00069       if ( ! item ) return;
00070 
00071       tip( m_listView->itemRect( i ), m_listView->tooltip( item, 0 ) );
00072 
00073     }
00074 
00075   private:
00076     KateFileList *m_listView;
00077 };
00078 
00079 //END ToolTip
00080 
00081 //BEGIN KateFileList
00082 KateFileList::KateFileList (KateMainWindow *main,
00083                             KateViewManager *_viewManager,
00084                             QWidget * parent, const char * name )
00085     :  KListView (parent, name)
00086     , m_sort( KateFileList::sortByID )
00087 {
00088   m_main = main;
00089   m_tooltip = new ToolTip( viewport(), this );
00090 
00091   // default colors
00092   m_viewShade = QColor( 51, 204, 255 );
00093   m_editShade = QColor( 255, 102, 153 );
00094   m_enableBgShading = true;
00095 
00096   setFocusPolicy ( QWidget::NoFocus  );
00097 
00098   viewManager = _viewManager;
00099 
00100   header()->hide();
00101   addColumn("Document Name");
00102 
00103   setSelectionMode( QListView::Single );
00104   setSorting( 0, true );
00105   setShowToolTips( false );
00106 
00107   setupActions ();
00108 
00109   for (uint i = 0; i < KateDocManager::self()->documents(); i++)
00110   {
00111     slotDocumentCreated (KateDocManager::self()->document(i));
00112     slotModChanged (KateDocManager::self()->document(i));
00113   }
00114 
00115   connect(KateDocManager::self(),SIGNAL(documentCreated(Kate::Document *)),
00116       this,SLOT(slotDocumentCreated(Kate::Document *)));
00117   connect(KateDocManager::self(),SIGNAL(documentDeleted(uint)),
00118       this,SLOT(slotDocumentDeleted(uint)));
00119 
00120   // don't Honour KDE single/double click setting, this files are already open,
00121   // no need for hassle of considering double-click
00122   connect(this,SIGNAL(clicked(QListViewItem *)),
00123       this,SLOT(slotActivateView(QListViewItem *)));
00124   connect(viewManager,SIGNAL(viewChanged()), this,SLOT(slotViewChanged()));
00125   connect(this,SIGNAL(contextMenuRequested( QListViewItem *, const QPoint &, int )),
00126       this,SLOT(slotMenu ( QListViewItem *, const QPoint &, int )));
00127 }
00128 
00129 KateFileList::~KateFileList ()
00130 {
00131   delete m_tooltip;
00132 }
00133 
00134 void KateFileList::setupActions ()
00135 {
00136   windowNext = KStdAction::back(this, SLOT(slotPrevDocument()), m_main->actionCollection());
00137   windowPrev = KStdAction::forward(this, SLOT(slotNextDocument()), m_main->actionCollection());
00138   KSelectAction *a = new KSelectAction( i18n("Sort &By"), 0,
00139       m_main->actionCollection(), "filelist_sortby"  );
00140   QStringList l;
00141   l << i18n("Opening Order") << i18n("Document Name") << i18n("URL");
00142   a->setItems( l );
00143   connect( a, SIGNAL(activated(int)), this, SLOT(setSortType(int)) );
00144 }
00145 
00146 void KateFileList::updateActions ()
00147 {
00148   windowNext->setEnabled(KateDocManager::self()->documents()  > 1);
00149   windowPrev->setEnabled(KateDocManager::self()->documents()  > 1);
00150 }
00151 
00152 void KateFileList::keyPressEvent(QKeyEvent *e) {
00153   if ( ( e->key() == Key_Return ) || ( e->key() == Key_Enter ) )
00154   {
00155     e->accept();
00156     slotActivateView( currentItem() );
00157   }
00158   else
00159   {
00160     KListView::keyPressEvent(e);
00161   }
00162 }
00163 
00164 // Protect single mode selection: don't let them
00165 // leftclick outside items.
00166 // ### if we get to accept keyboard navigation, set focus before
00167 // returning
00168 void KateFileList::contentsMousePressEvent( QMouseEvent *e )
00169 {
00170   if ( ! itemAt( contentsToViewport( e->pos() ) ) )
00171   return;
00172 
00173   KListView::contentsMousePressEvent( e );
00174 }
00175 
00176 void KateFileList::resizeEvent( QResizeEvent *e )
00177 {
00178   KListView::resizeEvent( e );
00179 
00180   // ### We may want to actually calculate the widest field,
00181   // since it's not automatically scrinked. If I add support for
00182   // tree or marks, the changes of the required width will vary
00183   // a lot with opening/closing of files and display changes for
00184   // the mark branches.
00185   int w = viewport()->width();
00186   if ( columnWidth( 0 ) < w )
00187     setColumnWidth( 0, w );
00188 }
00189 
00190 void KateFileList::slotNextDocument()
00191 {
00192   if ( ! currentItem() || childCount() == 0 )
00193     return;
00194 
00195   // ### more checking once more item types are added
00196 
00197   if ( currentItem()->nextSibling() )
00198     viewManager->activateView( ((KateFileListItem*)currentItem()->nextSibling())->documentNumber() );
00199   else
00200     viewManager->activateView( ((KateFileListItem *)firstChild())->documentNumber() );
00201 }
00202 
00203 void KateFileList::slotPrevDocument()
00204 {
00205   if ( ! currentItem() || childCount() == 0 )
00206     return;
00207 
00208   // ### more checking once more item types are added
00209 
00210   if ( currentItem()->itemAbove() )
00211     viewManager->activateView( ((KateFileListItem*)currentItem()->itemAbove())->documentNumber() );
00212   else
00213     viewManager->activateView( ((KateFileListItem *)lastItem())->documentNumber() );
00214 }
00215 
00216 void KateFileList::slotDocumentCreated (Kate::Document *doc)
00217 {
00218   new KateFileListItem( this, doc/*, doc->documentNumber()*/ );
00219   connect(doc,SIGNAL(modStateChanged(Kate::Document *)),this,SLOT(slotModChanged(Kate::Document *)));
00220   connect(doc,SIGNAL(nameChanged(Kate::Document *)),this,SLOT(slotNameChanged(Kate::Document *)));
00221   connect(doc,SIGNAL(modifiedOnDisc(Kate::Document *, bool, unsigned char)),this,SLOT(slotModifiedOnDisc(Kate::Document *, bool, unsigned char)));
00222 
00223   sort();
00224   updateActions ();
00225 }
00226 
00227 void KateFileList::slotDocumentDeleted (uint documentNumber)
00228 {
00229   QListViewItem * item = firstChild();
00230   while( item ) {
00231     if ( ((KateFileListItem *)item)->documentNumber() == documentNumber )
00232     {
00233 //       m_viewHistory.removeRef( (KateFileListItem *)item );
00234 //       m_editHistory.removeRef( (KateFileListItem *)item );
00235 
00236       removeItem( item );
00237 
00238       break;
00239     }
00240     item = item->nextSibling();
00241   }
00242 
00243   updateActions ();
00244 }
00245 
00246 void KateFileList::slotActivateView( QListViewItem *item )
00247 {
00248   if ( ! item || item->rtti() != RTTI_KateFileListItem )
00249     return;
00250 
00251   viewManager->activateView( ((KateFileListItem *)item)->documentNumber() );
00252 }
00253 
00254 void KateFileList::slotModChanged (Kate::Document *doc)
00255 {
00256   if (!doc) return;
00257 
00258   QListViewItem * item = firstChild();
00259   while( item )
00260   {
00261     if ( ((KateFileListItem *)item)->documentNumber() == doc->documentNumber() )
00262       break;
00263 
00264     item = item->nextSibling();
00265   }
00266 
00267   if ( ((KateFileListItem *)item)->document()->isModified() )
00268   {
00269     m_editHistory.removeRef( (KateFileListItem *)item );
00270     m_editHistory.prepend( (KateFileListItem *)item );
00271 
00272     for ( uint i=0; i <  m_editHistory.count(); i++ )
00273     {
00274       m_editHistory.at( i )->setEditHistPos( i+1 );
00275       repaintItem(  m_editHistory.at( i ) );
00276     }
00277   }
00278   else
00279     repaintItem( item );
00280 }
00281 
00282 void KateFileList::slotModifiedOnDisc (Kate::Document *doc, bool, unsigned char r)
00283 {
00284   slotModChanged( doc );
00285 }
00286 
00287 void KateFileList::slotNameChanged (Kate::Document *doc)
00288 {
00289   if (!doc) return;
00290 
00291   // ### using nextSibling to *only* look at toplevel items.
00292   // child items could be marks for example
00293   QListViewItem * item = firstChild();
00294   while( item ) {
00295     if ( ((KateFileListItem*)item)->document() == doc )
00296     {
00297       item->setText( 0, doc->docName() );
00298       repaintItem( item );
00299       break;
00300     }
00301     item = item->nextSibling();
00302   }
00303   updateSort();
00304 }
00305 
00306 void KateFileList::slotViewChanged ()
00307 {
00308   if (!viewManager->activeView()) return;
00309 
00310   Kate::View *view = viewManager->activeView();
00311   uint dn = view->getDoc()->documentNumber();
00312 
00313   QListViewItem * i = firstChild();
00314   while( i ) {
00315     if ( ((KateFileListItem *)i)->documentNumber() == dn )
00316     {
00317       break;
00318     }
00319     i = i->nextSibling();
00320   }
00321 
00322   if ( ! i )
00323     return;
00324 
00325   KateFileListItem *item = (KateFileListItem*)i;
00326   setCurrentItem( item );
00327 
00328   // ### During load of file lists, all the loaded views gets active.
00329   // Do something to avoid shading them -- maybe not creating views, just
00330   // open the documents???
00331 
00332 
00333 //   int p = 0;
00334 //   if (  m_viewHistory.count() )
00335 //   {
00336 //     int p =  m_viewHistory.findRef( item ); // only repaint items that needs it
00337 //   }
00338 
00339   m_viewHistory.removeRef( item );
00340   m_viewHistory.prepend( item );
00341 
00342   for ( uint i=0; i <  m_viewHistory.count(); i++ )
00343   {
00344     m_viewHistory.at( i )->setViewHistPos( i+1 );
00345     repaintItem(  m_viewHistory.at( i ) );
00346   }
00347 
00348 }
00349 
00350 void KateFileList::slotMenu ( QListViewItem *item, const QPoint &p, int /*col*/ )
00351 {
00352   if (!item)
00353     return;
00354 
00355   QPopupMenu *menu = (QPopupMenu*) ((viewManager->mainWindow())->factory()->container("filelist_popup", viewManager->mainWindow()));
00356 
00357   if (menu)
00358     menu->exec(p);
00359 }
00360 
00361 QString KateFileList::tooltip( QListViewItem *item, int )
00362 {
00363   KateFileListItem *i = ((KateFileListItem*)item);
00364   if ( ! i ) return QString::null;
00365 
00366   QString str;
00367   const KateDocumentInfo *info = KateDocManager::self()->documentInfo(i->document());
00368 
00369   if (info && info->modifiedOnDisc)
00370   {
00371     if (info->modifiedOnDiscReason == 1)
00372       str += i18n("<b>This file was changed (modified) on disk by another program.</b><br />");
00373     else if (info->modifiedOnDiscReason == 2)
00374       str += i18n("<b>This file was changed (created) on disk by another program.</b><br />");
00375     else if (info->modifiedOnDiscReason == 3)
00376       str += i18n("<b>This file was changed (deleted) on disk by another program.</b><br />");
00377   }
00378 
00379   str += i->document()->url().prettyURL();
00380   return str;
00381 }
00382 
00383 
00384 void KateFileList::setSortType (int s)
00385 {
00386   m_sort = s;
00387   updateSort ();
00388 }
00389 
00390 void KateFileList::updateSort ()
00391 {
00392   sort ();
00393 }
00394 
00395 void KateFileList::readConfig( KConfig *config, const QString &group )
00396 {
00397   QString oldgroup = config->group();
00398   config->setGroup( group );
00399 
00400   setSortType( config->readNumEntry( "Sort Type", sortByID ) );
00401   m_viewShade = config->readColorEntry( "View Shade", &m_viewShade );
00402   m_editShade = config->readColorEntry( "Edit Shade", &m_editShade );
00403   m_enableBgShading = config->readBoolEntry( "Shading Enabled", &m_enableBgShading );
00404 
00405   config->setGroup( oldgroup );
00406 }
00407 
00408 void KateFileList::writeConfig( KConfig *config, const QString &group )
00409 {
00410   QString oldgroup = config->group();
00411   config->setGroup( group );
00412 
00413   config->writeEntry( "Sort Type", m_sort );
00414   config->writeEntry( "View Shade", m_viewShade );
00415   config->writeEntry( "Edit Shade", m_editShade );
00416   config->writeEntry( "Shading Enabled", m_enableBgShading );
00417 
00418   config->setGroup( oldgroup );
00419 }
00420 
00421 void KateFileList::takeItem( QListViewItem *item )
00422 {
00423   if ( item->rtti() == RTTI_KateFileListItem )
00424   {
00425     m_editHistory.removeRef( (KateFileListItem*)item );
00426     m_viewHistory.removeRef( (KateFileListItem*)item );
00427   }
00428   QListView::takeItem( item );
00429 }
00430 //END KateFileList
00431 
00432 //BEGIN KateFileListItem
00433 KateFileListItem::KateFileListItem( QListView* lv,
00434                     Kate::Document *_doc )
00435   : QListViewItem( lv, _doc->docName() ),
00436     doc( _doc ),
00437     m_viewhistpos( 0 ),
00438     m_edithistpos( 0 ),
00439     m_docNumber( _doc->documentNumber() )
00440 {
00441 }
00442 
00443 KateFileListItem::~KateFileListItem()
00444 {
00445 }
00446 
00447 const QPixmap *KateFileListItem::pixmap ( int column ) const
00448 {
00449   if ( column == 0) {
00450     static QPixmap noPm = SmallIcon ("null");
00451     static QPixmap modPm = SmallIcon("modified");
00452     static QPixmap discPm = SmallIcon("modonhd");
00453     static QPixmap modmodPm = SmallIcon("modmod");
00454 
00455     const KateDocumentInfo *info = KateDocManager::self()->documentInfo(doc);
00456 
00457     if (info && info->modifiedOnDisc)
00458       return doc->isModified() ? &modmodPm : &discPm;
00459     else
00460       return doc->isModified() ? &modPm : &noPm;
00461   }
00462   return 0;
00463 }
00464 
00465 void KateFileListItem::paintCell( QPainter *painter, const QColorGroup & cg, int column, int width, int align )
00466 {
00467   KateFileList *fl = (KateFileList*)listView();
00468   if ( ! fl ) return;
00469 
00470   if ( column == 0 ) {
00471     QColorGroup cgNew = cg;
00472 
00473     // replace the base color with a different shading if necessary...
00474     if ( fl->shadingEnabled() && m_viewhistpos > 1 )
00475     {
00476       QColor b( cg.base() );
00477 
00478       QColor shade = fl->viewShade();
00479       QColor eshade = fl->editShade();
00480       int hc = fl->histCount();
00481       // If this file is in the edit history, blend in the eshade
00482       // color. The blend is weighted by the position in the editing history
00483       if ( fl->shadingEnabled() && m_edithistpos > 0 )
00484       {
00485         int ec = fl->editHistCount();
00486         int v = hc-m_viewhistpos;
00487         int e = ec-m_edithistpos+1;
00488         e = e*e;
00489         int n = QMAX(v + e, 1);
00490         shade.setRgb(
00491             ((shade.red()*v) + (eshade.red()*e))/n,
00492             ((shade.green()*v) + (eshade.green()*e))/n,
00493             ((shade.blue()*v) + (eshade.blue()*e))/n
00494                     );
00495       }
00496       // blend in the shade color.
00497       // max transperancy < .5, latest is most colored.
00498       float t = (0.5/hc)*(hc-m_viewhistpos+1);
00499       b.setRgb(
00500           (int)((b.red()*(1-t)) + (shade.red()*t)),
00501           (int)((b.green()*(1-t)) + (shade.green()*t)),
00502           (int)((b.blue()*(1-t)) + (shade.blue()*t))
00503               );
00504 
00505       cgNew.setColor(QColorGroup::Base, b);
00506     }
00507 
00508     QListViewItem::paintCell( painter, cgNew, column, width, align );
00509   } else {
00510     QListViewItem::paintCell( painter, cg, column, width, align );
00511   }
00512 
00513 }
00514 
00515 int KateFileListItem::compare ( QListViewItem * i, int col, bool ascending ) const
00516 {
00517   if ( i->rtti() == RTTI_KateFileListItem )
00518   {
00519     switch( ((KateFileList*)listView())->sortType() )
00520     {
00521       case KateFileList::sortByID:
00522       {
00523 
00524         int d = (int)doc->documentNumber() - ((KateFileListItem*)i)->documentNumber();
00525         return ascending ? d : -d;
00526         break;
00527       }
00528       case KateFileList::sortByURL:
00529         return doc->url().prettyURL().compare( ((KateFileListItem*)i)->document()->url().prettyURL() );
00530         break;
00531       default:
00532         return QListViewItem::compare( i, col, ascending );
00533     }
00534   }
00535   return 0;
00536 }
00537 //END KateFileListItem
00538 
00539 //BEGIN KFLConfigPage
00540 KFLConfigPage::KFLConfigPage( QWidget* parent, const char *name, KateFileList *fl )
00541   :  Kate::ConfigPage( parent, name ),
00542     m_filelist( fl ),
00543     m_changed( false )
00544 {
00545   QVBoxLayout *lo1 = new QVBoxLayout( this );
00546   int spacing = KDialog::spacingHint();
00547   lo1->setSpacing( spacing );
00548 
00549   QGroupBox *gb = new QGroupBox( 1, Qt::Horizontal, i18n("Background Shading"), this );
00550   lo1->addWidget( gb );
00551 
00552   QWidget *g = new QWidget( gb );
00553   QGridLayout *lo = new QGridLayout( g, 2, 2 );
00554   lo->setSpacing( KDialog::spacingHint() );
00555   cbEnableShading = new QCheckBox( i18n("&Enable background shading"), g );
00556   lo->addMultiCellWidget( cbEnableShading, 1, 1, 0, 1 );
00557 
00558   kcbViewShade = new KColorButton( g );
00559   lViewShade = new QLabel( kcbViewShade, i18n("&Viewed documents' shade:"), g );
00560   lo->addWidget( lViewShade, 2, 0 );
00561   lo->addWidget( kcbViewShade, 2, 1 );
00562 
00563   kcbEditShade = new KColorButton( g );
00564   lEditShade = new QLabel( kcbEditShade, i18n("&Modified documents' shade:"), g );
00565   lo->addWidget( lEditShade, 3, 0 );
00566   lo->addWidget( kcbEditShade, 3, 1 );
00567 
00568   lo1->insertStretch( -1, 10 );
00569 
00570   QWhatsThis::add( cbEnableShading, i18n(
00571       "When background shading is enabled, documents that have been viewed "
00572       "or edited within the current session will have a shaded background. "
00573       "The most recent documents have the strongest shade.") );
00574   QWhatsThis::add( kcbViewShade, i18n(
00575       "Set the color for shading viewed documents.") );
00576   QWhatsThis::add( kcbEditShade, i18n(
00577       "Set the color for modified documents. This color is blended into "
00578       "the color for viewed files. The most recently edited documents get "
00579       "most of this color.") );
00580 
00581   reload();
00582 
00583   slotEnableChanged();
00584   connect( cbEnableShading, SIGNAL(toggled(bool)), this, SLOT(slotMyChanged()) );
00585   connect( cbEnableShading, SIGNAL(toggled(bool)), this, SLOT(slotEnableChanged()) );
00586   connect( kcbViewShade, SIGNAL(changed(const QColor&)), this, SLOT(slotMyChanged()) );
00587   connect( kcbEditShade, SIGNAL(changed(const QColor&)), this, SLOT(slotMyChanged()) );
00588 }
00589 
00590 void KFLConfigPage::apply()
00591 {
00592   if ( ! m_changed )
00593     return;
00594   m_changed = false;
00595 
00596   // Change settings in the filelist
00597   m_filelist->m_viewShade = kcbViewShade->color();
00598   m_filelist->m_editShade = kcbEditShade->color();
00599   m_filelist->m_enableBgShading = cbEnableShading->isChecked();
00600   // repaint the affected items
00601   m_filelist->triggerUpdate();
00602 }
00603 
00604 void KFLConfigPage::reload()
00605 {
00606   // read in from config file
00607   KConfig *config = kapp->config();
00608   config->setGroup( "Filelist" );
00609   cbEnableShading->setChecked( config->readBoolEntry("Shading Enabled", &m_filelist->m_enableBgShading ) );
00610   kcbViewShade->setColor( config->readColorEntry("View Shade", &m_filelist->m_viewShade ) );
00611   kcbEditShade->setColor( config->readColorEntry("Edit Shade", &m_filelist->m_editShade ) );
00612   m_changed = false;
00613 }
00614 
00615 void KFLConfigPage::slotEnableChanged()
00616 {
00617   kcbViewShade->setEnabled( cbEnableShading->isChecked() );
00618   kcbEditShade->setEnabled( cbEnableShading->isChecked() );
00619   lViewShade->setEnabled( cbEnableShading->isChecked() );
00620   lEditShade->setEnabled( cbEnableShading->isChecked() );
00621 }
00622 
00623 void KFLConfigPage::slotMyChanged()
00624 {
00625   m_changed = true;
00626   slotChanged();
00627 }
00628 
00629 //END KFLConfigPage
00630 
00631 
00632 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Sep 30 18:40:31 2005 by doxygen 1.4.3 written by Dimitri van Heesch, © 1997-2003