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 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
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
00482
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
00497
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
00538
00539
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
00597 m_filelist->m_viewShade = kcbViewShade->color();
00598 m_filelist->m_editShade = kcbEditShade->color();
00599 m_filelist->m_enableBgShading = cbEnableShading->isChecked();
00600
00601 m_filelist->triggerUpdate();
00602 }
00603
00604 void KFLConfigPage::reload()
00605 {
00606
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
00630
00631
00632