00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00051
00052
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
00080
00081
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
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
00121
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
00165
00166
00167
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
00181
00182
00183
00184
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
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
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 );
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
00234
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
00292
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
00329
00330
00331
00332
00333
00334
00335
00336
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 )
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
00431
00432
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 int KateFileListItem::height() const
00448 {
00449 int h;
00450 static int iSize = IconSize( KIcon::Small );
00451 if ( text( 0 ).isEmpty() )
00452 h = iSize;
00453 else
00454 h = QMAX( iSize, listView()->fontMetrics().lineSpacing() + 1 );
00455
00456 return QMAX( h, QApplication::globalStrut().height() );
00457 }
00458
00459 int KateFileListItem::width( const QFontMetrics &fm, const QListView* , int column ) const
00460 {
00461 static int iSize = IconSize( KIcon::Small );
00462 if ( text( 0 ).isEmpty() )
00463 return QMAX( iSize + 6, QApplication::globalStrut().width() );
00464
00465 return QMAX( iSize + fm.width( text(column) ) + 6, QApplication::globalStrut().width() );
00466 }
00467
00468 void KateFileListItem::paintCell( QPainter *painter, const QColorGroup & cg, int column, int width, int align )
00469 {
00470 KateFileList *fl = (KateFileList*)listView();
00471 if ( ! fl ) return;
00472
00473 switch ( column ) {
00474 case 0:
00475 {
00476 static QPixmap noPm = SmallIcon ("null");
00477 static QPixmap modPm = SmallIcon("modified");
00478 static QPixmap discPm = SmallIcon("modonhd");
00479 static QPixmap modmodPm = SmallIcon("modmod");
00480
00481 const KateDocumentInfo *info = KateDocManager::self()->documentInfo(doc);
00482
00483 QColor b( cg.base() );
00484 if ( fl->shadingEnabled() && m_viewhistpos > 1 )
00485 {
00486 QColor shade = fl->viewShade();
00487 QColor eshade = fl->editShade();
00488 int hc = fl->histCount();
00489
00490
00491 if ( fl->shadingEnabled() && m_edithistpos > 0 )
00492 {
00493 int ec = fl->editHistCount();
00494 int v = hc-m_viewhistpos;
00495 int e = ec-m_edithistpos+1;
00496 e = e*e;
00497 int n = QMAX(v + e, 1);
00498 shade.setRgb(
00499 ((shade.red()*v) + (eshade.red()*e))/n,
00500 ((shade.green()*v) + (eshade.green()*e))/n,
00501 ((shade.blue()*v) + (eshade.blue()*e))/n
00502 );
00503 }
00504
00505
00506 float t = (0.5/hc)*(hc-m_viewhistpos+1);
00507 b.setRgb(
00508 (int)((b.red()*(1-t)) + (shade.red()*t)),
00509 (int)((b.green()*(1-t)) + (shade.green()*t)),
00510 (int)((b.blue()*(1-t)) + (shade.blue()*t))
00511 );
00512 }
00513
00514 painter->fillRect( 0, 0, width, height(), isSelected() ? cg.highlight() : b );
00515
00516 if (info && info->modifiedOnDisc)
00517 painter->drawPixmap( 3, 0, doc->isModified() ? modmodPm : discPm );
00518 else
00519 painter->drawPixmap( 3, 0, doc->isModified() ? modPm : noPm );
00520
00521 if ( !text( 0 ).isEmpty() )
00522 {
00523 QFontMetrics fm = painter->fontMetrics();
00524 painter->setPen( isSelected() ? cg.highlightedText() : cg.text() );
00525
00526 static int iSize = IconSize( KIcon::Small );
00527 int yPos;
00528
00529 if ( iSize < fm.height() )
00530 yPos = fm.ascent() + fm.leading()/2;
00531 else
00532 yPos = iSize/2 - fm.height()/2 + fm.ascent();
00533
00534 painter->drawText( iSize + 4, yPos,
00535 KStringHandler::rPixelSqueeze( text(0), painter->fontMetrics(), width - 20 ) );
00536 }
00537 break;
00538 }
00539 default:
00540 QListViewItem::paintCell( painter, cg, column, width, align );
00541 }
00542 }
00543
00544 int KateFileListItem::compare ( QListViewItem * i, int col, bool ascending ) const
00545 {
00546 if ( i->rtti() == RTTI_KateFileListItem )
00547 {
00548 switch( ((KateFileList*)listView())->sortType() )
00549 {
00550 case KateFileList::sortByID:
00551 {
00552
00553 int d = (int)doc->documentNumber() - ((KateFileListItem*)i)->documentNumber();
00554 return ascending ? d : -d;
00555 break;
00556 }
00557 case KateFileList::sortByURL:
00558 return doc->url().prettyURL().compare( ((KateFileListItem*)i)->document()->url().prettyURL() );
00559 break;
00560 default:
00561 return QListViewItem::compare( i, col, ascending );
00562 }
00563 }
00564 return 0;
00565 }
00566
00567
00568
00569 KFLConfigPage::KFLConfigPage( QWidget* parent, const char *name, KateFileList *fl )
00570 : Kate::ConfigPage( parent, name ),
00571 m_filelist( fl ),
00572 m_changed( false )
00573 {
00574 QVBoxLayout *lo1 = new QVBoxLayout( this );
00575 int spacing = KDialog::spacingHint();
00576 lo1->setSpacing( spacing );
00577
00578 QGroupBox *gb = new QGroupBox( 1, Qt::Horizontal, i18n("Background Shading"), this );
00579 lo1->addWidget( gb );
00580
00581 QWidget *g = new QWidget( gb );
00582 QGridLayout *lo = new QGridLayout( g, 2, 2 );
00583 lo->setSpacing( KDialog::spacingHint() );
00584 cbEnableShading = new QCheckBox( i18n("&Enable background shading"), g );
00585 lo->addMultiCellWidget( cbEnableShading, 1, 1, 0, 1 );
00586
00587 kcbViewShade = new KColorButton( g );
00588 lViewShade = new QLabel( kcbViewShade, i18n("&Viewed documents' shade:"), g );
00589 lo->addWidget( lViewShade, 2, 0 );
00590 lo->addWidget( kcbViewShade, 2, 1 );
00591
00592 kcbEditShade = new KColorButton( g );
00593 lEditShade = new QLabel( kcbEditShade, i18n("&Modified documents' shade:"), g );
00594 lo->addWidget( lEditShade, 3, 0 );
00595 lo->addWidget( kcbEditShade, 3, 1 );
00596
00597 lo1->insertStretch( -1, 10 );
00598
00599 QWhatsThis::add( cbEnableShading, i18n(
00600 "When background shading is enabled, documents that have been viewed "
00601 "or edited within the current session will have a shaded background. "
00602 "The most recent documents have the strongest shade.") );
00603 QWhatsThis::add( kcbViewShade, i18n(
00604 "Set the color for shading viewed documents.") );
00605 QWhatsThis::add( kcbEditShade, i18n(
00606 "Set the color for modified documents. This color is blended into "
00607 "the color for viewed files. The most recently edited documents get "
00608 "most of this color.") );
00609
00610 reload();
00611
00612 slotEnableChanged();
00613 connect( cbEnableShading, SIGNAL(toggled(bool)), this, SLOT(slotMyChanged()) );
00614 connect( cbEnableShading, SIGNAL(toggled(bool)), this, SLOT(slotEnableChanged()) );
00615 connect( kcbViewShade, SIGNAL(changed(const QColor&)), this, SLOT(slotMyChanged()) );
00616 connect( kcbEditShade, SIGNAL(changed(const QColor&)), this, SLOT(slotMyChanged()) );
00617 }
00618
00619 void KFLConfigPage::apply()
00620 {
00621 if ( ! m_changed )
00622 return;
00623 m_changed = false;
00624
00625
00626 m_filelist->m_viewShade = kcbViewShade->color();
00627 m_filelist->m_editShade = kcbEditShade->color();
00628 m_filelist->m_enableBgShading = cbEnableShading->isChecked();
00629
00630 m_filelist->triggerUpdate();
00631 }
00632
00633 void KFLConfigPage::reload()
00634 {
00635
00636 KConfig *config = kapp->config();
00637 config->setGroup( "Filelist" );
00638 cbEnableShading->setChecked( config->readBoolEntry("Shading Enabled", &m_filelist->m_enableBgShading ) );
00639 kcbViewShade->setColor( config->readColorEntry("View Shade", &m_filelist->m_viewShade ) );
00640 kcbEditShade->setColor( config->readColorEntry("Edit Shade", &m_filelist->m_editShade ) );
00641 m_changed = false;
00642 }
00643
00644 void KFLConfigPage::slotEnableChanged()
00645 {
00646 kcbViewShade->setEnabled( cbEnableShading->isChecked() );
00647 kcbEditShade->setEnabled( cbEnableShading->isChecked() );
00648 lViewShade->setEnabled( cbEnableShading->isChecked() );
00649 lEditShade->setEnabled( cbEnableShading->isChecked() );
00650 }
00651
00652 void KFLConfigPage::slotMyChanged()
00653 {
00654 m_changed = true;
00655 slotChanged();
00656 }
00657
00658
00659
00660
00661