diff options
Diffstat (limited to 'kate/app/katefilelist.cpp')
-rw-r--r-- | kate/app/katefilelist.cpp | 652 |
1 files changed, 652 insertions, 0 deletions
diff --git a/kate/app/katefilelist.cpp b/kate/app/katefilelist.cpp new file mode 100644 index 000000000..8c350d45a --- /dev/null +++ b/kate/app/katefilelist.cpp @@ -0,0 +1,652 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> + Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org> + Copyright (C) 2001 Anders Lund <anders.lund@lund.tdcadsl.dk> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +//BEGIN Includes +#include "katefilelist.h" +#include "katefilelist.moc" + +#include "katedocmanager.h" +#include "kateviewmanager.h" +#include "katemainwindow.h" + +#include <qapplication.h> +#include <qpainter.h> +#include <qpopupmenu.h> +#include <qheader.h> +#include <qcolor.h> +#include <qcheckbox.h> +#include <qhbox.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qwhatsthis.h> + +#include <kiconloader.h> +#include <kconfig.h> +#include <klocale.h> +#include <kglobalsettings.h> +#include <kpassivepopup.h> +#include <kdebug.h> +#include <kapplication.h> +#include <kstringhandler.h> +#include <kcolorbutton.h> +#include <kdialog.h> +//END Includes + +//BEGIN ToolTip +class ToolTip : public QToolTip +{ + public: + ToolTip( QWidget *parent, KateFileList *lv ) + : QToolTip( parent ), + m_listView( lv ) + { + } + virtual ~ToolTip() {}; + + void maybeTip( const QPoint &pos ) + { + QListViewItem *i = m_listView->itemAt( pos ); + if ( ! i ) return; + + KateFileListItem *item = ((KateFileListItem*)i); + if ( ! item ) return; + + tip( m_listView->itemRect( i ), m_listView->tooltip( item, 0 ) ); + + } + + private: + KateFileList *m_listView; +}; + +//END ToolTip + +//BEGIN KateFileList +KateFileList::KateFileList (KateMainWindow *main, + KateViewManager *_viewManager, + QWidget * parent, const char * name ) + : KListView (parent, name) + , m_sort( KateFileList::sortByID ) +{ + m_main = main; + m_tooltip = new ToolTip( viewport(), this ); + + // default colors + m_viewShade = QColor( 51, 204, 255 ); + m_editShade = QColor( 255, 102, 153 ); + m_enableBgShading = false; + + setFocusPolicy ( QWidget::NoFocus ); + + viewManager = _viewManager; + + header()->hide(); + addColumn("Document Name"); + + setSelectionMode( QListView::Single ); + setSorting( 0, true ); + setShowToolTips( false ); + + setupActions (); + + for (uint i = 0; i < KateDocManager::self()->documents(); i++) + { + slotDocumentCreated (KateDocManager::self()->document(i)); + slotModChanged (KateDocManager::self()->document(i)); + } + + connect(KateDocManager::self(),SIGNAL(documentCreated(Kate::Document *)), + this,SLOT(slotDocumentCreated(Kate::Document *))); + connect(KateDocManager::self(),SIGNAL(documentDeleted(uint)), + this,SLOT(slotDocumentDeleted(uint))); + + // don't Honour KDE single/double click setting, this files are already open, + // no need for hassle of considering double-click + connect(this,SIGNAL(selectionChanged(QListViewItem *)), + this,SLOT(slotActivateView(QListViewItem *))); + connect(viewManager,SIGNAL(viewChanged()), this,SLOT(slotViewChanged())); + connect(this,SIGNAL(contextMenuRequested( QListViewItem *, const QPoint &, int )), + this,SLOT(slotMenu ( QListViewItem *, const QPoint &, int ))); +} + +KateFileList::~KateFileList () +{ + delete m_tooltip; +} + +void KateFileList::setupActions () +{ + windowNext = KStdAction::back(this, SLOT(slotPrevDocument()), m_main->actionCollection()); + windowPrev = KStdAction::forward(this, SLOT(slotNextDocument()), m_main->actionCollection()); + sortAction = new KSelectAction( i18n("Sort &By"), 0, + m_main->actionCollection(), "filelist_sortby" ); + QStringList l; + l << i18n("Opening Order") << i18n("Document Name") << i18n("URL"); + sortAction->setItems( l ); + connect( sortAction, SIGNAL(activated(int)), this, SLOT(setSortType(int)) ); +} + +void KateFileList::updateActions () +{ + windowNext->setEnabled(KateDocManager::self()->documents() > 1); + windowPrev->setEnabled(KateDocManager::self()->documents() > 1); +} + +void KateFileList::keyPressEvent(QKeyEvent *e) { + if ( ( e->key() == Key_Return ) || ( e->key() == Key_Enter ) ) + { + e->accept(); + slotActivateView( currentItem() ); + } + else + { + KListView::keyPressEvent(e); + } +} + +// Protect single mode selection: don't let them +// leftclick outside items. +// ### if we get to accept keyboard navigation, set focus before +// returning +void KateFileList::contentsMousePressEvent( QMouseEvent *e ) +{ + if ( ! itemAt( contentsToViewport( e->pos() ) ) ) + return; + + KListView::contentsMousePressEvent( e ); +} + +void KateFileList::resizeEvent( QResizeEvent *e ) +{ + KListView::resizeEvent( e ); + + // ### We may want to actually calculate the widest field, + // since it's not automatically scrinked. If I add support for + // tree or marks, the changes of the required width will vary + // a lot with opening/closing of files and display changes for + // the mark branches. + int w = viewport()->width(); + if ( columnWidth( 0 ) < w ) + setColumnWidth( 0, w ); +} + +void KateFileList::slotNextDocument() +{ + if ( ! currentItem() || childCount() == 0 ) + return; + + // ### more checking once more item types are added + + if ( currentItem()->nextSibling() ) + viewManager->activateView( ((KateFileListItem*)currentItem()->nextSibling())->documentNumber() ); + else + viewManager->activateView( ((KateFileListItem *)firstChild())->documentNumber() ); +} + +void KateFileList::slotPrevDocument() +{ + if ( ! currentItem() || childCount() == 0 ) + return; + + // ### more checking once more item types are added + + if ( currentItem()->itemAbove() ) + viewManager->activateView( ((KateFileListItem*)currentItem()->itemAbove())->documentNumber() ); + else + viewManager->activateView( ((KateFileListItem *)lastItem())->documentNumber() ); +} + +void KateFileList::slotDocumentCreated (Kate::Document *doc) +{ + new KateFileListItem( this, doc/*, doc->documentNumber()*/ ); + connect(doc,SIGNAL(modStateChanged(Kate::Document *)),this,SLOT(slotModChanged(Kate::Document *))); + connect(doc,SIGNAL(nameChanged(Kate::Document *)),this,SLOT(slotNameChanged(Kate::Document *))); + connect(doc,SIGNAL(modifiedOnDisc(Kate::Document *, bool, unsigned char)),this,SLOT(slotModifiedOnDisc(Kate::Document *, bool, unsigned char))); + + sort(); + updateActions (); +} + +void KateFileList::slotDocumentDeleted (uint documentNumber) +{ + QListViewItem * item = firstChild(); + while( item ) { + if ( ((KateFileListItem *)item)->documentNumber() == documentNumber ) + { +// m_viewHistory.removeRef( (KateFileListItem *)item ); +// m_editHistory.removeRef( (KateFileListItem *)item ); + + removeItem( item ); + + break; + } + item = item->nextSibling(); + } + + updateActions (); +} + +void KateFileList::slotActivateView( QListViewItem *item ) +{ + if ( ! item || item->rtti() != RTTI_KateFileListItem ) + return; + + viewManager->activateView( ((KateFileListItem *)item)->documentNumber() ); +} + +void KateFileList::slotModChanged (Kate::Document *doc) +{ + if (!doc) return; + + QListViewItem * item = firstChild(); + while( item ) + { + if ( ((KateFileListItem *)item)->documentNumber() == doc->documentNumber() ) + break; + + item = item->nextSibling(); + } + + if ( ((KateFileListItem *)item)->document()->isModified() ) + { + m_editHistory.removeRef( (KateFileListItem *)item ); + m_editHistory.prepend( (KateFileListItem *)item ); + + for ( uint i=0; i < m_editHistory.count(); i++ ) + { + m_editHistory.at( i )->setEditHistPos( i+1 ); + repaintItem( m_editHistory.at( i ) ); + } + } + else + repaintItem( item ); +} + +void KateFileList::slotModifiedOnDisc (Kate::Document *doc, bool, unsigned char) +{ + slotModChanged( doc ); +} + +void KateFileList::slotNameChanged (Kate::Document *doc) +{ + if (!doc) return; + + // ### using nextSibling to *only* look at toplevel items. + // child items could be marks for example + QListViewItem * item = firstChild(); + while( item ) { + if ( ((KateFileListItem*)item)->document() == doc ) + { + item->setText( 0, doc->docName() ); + repaintItem( item ); + break; + } + item = item->nextSibling(); + } + updateSort(); +} + +void KateFileList::slotViewChanged () +{ + if (!viewManager->activeView()) return; + + Kate::View *view = viewManager->activeView(); + uint dn = view->getDoc()->documentNumber(); + + QListViewItem * i = firstChild(); + while( i ) { + if ( ((KateFileListItem *)i)->documentNumber() == dn ) + { + break; + } + i = i->nextSibling(); + } + + if ( ! i ) + return; + + KateFileListItem *item = (KateFileListItem*)i; + setCurrentItem( item ); + + // ### During load of file lists, all the loaded views gets active. + // Do something to avoid shading them -- maybe not creating views, just + // open the documents??? + + +// int p = 0; +// if ( m_viewHistory.count() ) +// { +// int p = m_viewHistory.findRef( item ); // only repaint items that needs it +// } + + m_viewHistory.removeRef( item ); + m_viewHistory.prepend( item ); + + for ( uint i=0; i < m_viewHistory.count(); i++ ) + { + m_viewHistory.at( i )->setViewHistPos( i+1 ); + repaintItem( m_viewHistory.at( i ) ); + } + +} + +void KateFileList::slotMenu ( QListViewItem *item, const QPoint &p, int /*col*/ ) +{ + if (!item) + return; + + QPopupMenu *menu = (QPopupMenu*) ((viewManager->mainWindow())->factory()->container("filelist_popup", viewManager->mainWindow())); + + if (menu) + menu->exec(p); +} + +QString KateFileList::tooltip( QListViewItem *item, int ) +{ + KateFileListItem *i = ((KateFileListItem*)item); + if ( ! i ) return QString::null; + + QString str; + const KateDocumentInfo *info = KateDocManager::self()->documentInfo(i->document()); + + if (info && info->modifiedOnDisc) + { + if (info->modifiedOnDiscReason == 1) + str += i18n("<b>This file was changed (modified) on disk by another program.</b><br />"); + else if (info->modifiedOnDiscReason == 2) + str += i18n("<b>This file was changed (created) on disk by another program.</b><br />"); + else if (info->modifiedOnDiscReason == 3) + str += i18n("<b>This file was changed (deleted) on disk by another program.</b><br />"); + } + + str += i->document()->url().prettyURL(); + return str; +} + + +void KateFileList::setSortType (int s) +{ + m_sort = s; + updateSort (); +} + +void KateFileList::updateSort () +{ + sort (); +} + +void KateFileList::readConfig( KConfig *config, const QString &group ) +{ + QString oldgroup = config->group(); + config->setGroup( group ); + + setSortType( config->readNumEntry( "Sort Type", sortByID ) ); + m_viewShade = config->readColorEntry( "View Shade", &m_viewShade ); + m_editShade = config->readColorEntry( "Edit Shade", &m_editShade ); + m_enableBgShading = config->readBoolEntry( "Shading Enabled", &m_enableBgShading ); + + sortAction->setCurrentItem( sortType() ); + + config->setGroup( oldgroup ); +} + +void KateFileList::writeConfig( KConfig *config, const QString &group ) +{ + QString oldgroup = config->group(); + config->setGroup( group ); + + config->writeEntry( "Sort Type", m_sort ); + config->writeEntry( "View Shade", m_viewShade ); + config->writeEntry( "Edit Shade", m_editShade ); + config->writeEntry( "Shading Enabled", m_enableBgShading ); + + config->setGroup( oldgroup ); +} + +void KateFileList::takeItem( QListViewItem *item ) +{ + if ( item->rtti() == RTTI_KateFileListItem ) + { + m_editHistory.removeRef( (KateFileListItem*)item ); + m_viewHistory.removeRef( (KateFileListItem*)item ); + } + QListView::takeItem( item ); +} +//END KateFileList + +//BEGIN KateFileListItem +KateFileListItem::KateFileListItem( QListView* lv, + Kate::Document *_doc ) + : QListViewItem( lv, _doc->docName() ), + doc( _doc ), + m_viewhistpos( 0 ), + m_edithistpos( 0 ), + m_docNumber( _doc->documentNumber() ) +{ +} + +KateFileListItem::~KateFileListItem() +{ +} + +const QPixmap *KateFileListItem::pixmap ( int column ) const +{ + if ( column == 0) { + static QPixmap noPm = SmallIcon ("null"); + static QPixmap modPm = SmallIcon("modified"); + static QPixmap discPm = SmallIcon("modonhd"); + static QPixmap modmodPm = SmallIcon("modmod"); + + const KateDocumentInfo *info = KateDocManager::self()->documentInfo(doc); + + if (info && info->modifiedOnDisc) + return doc->isModified() ? &modmodPm : &discPm; + else + return doc->isModified() ? &modPm : &noPm; + } + + return 0; +} + +void KateFileListItem::paintCell( QPainter *painter, const QColorGroup & cg, int column, int width, int align ) +{ + KateFileList *fl = (KateFileList*)listView(); + if ( ! fl ) return; + + if ( column == 0 ) + { + QColorGroup cgNew = cg; + + // replace the base color with a different shading if necessary... + if ( fl->shadingEnabled() && m_viewhistpos > 1 ) + { + QColor b( cg.base() ); + + QColor shade = fl->viewShade(); + QColor eshade = fl->editShade(); + int hc = fl->histCount(); + // If this file is in the edit history, blend in the eshade + // color. The blend is weighted by the position in the editing history + if ( fl->shadingEnabled() && m_edithistpos > 0 ) + { + int ec = fl->editHistCount(); + int v = hc-m_viewhistpos; + int e = ec-m_edithistpos+1; + e = e*e; + int n = QMAX(v + e, 1); + shade.setRgb( + ((shade.red()*v) + (eshade.red()*e))/n, + ((shade.green()*v) + (eshade.green()*e))/n, + ((shade.blue()*v) + (eshade.blue()*e))/n + ); + } + // blend in the shade color. + // max transperancy < .5, latest is most colored. + float t = (0.5/hc)*(hc-m_viewhistpos+1); + b.setRgb( + (int)((b.red()*(1-t)) + (shade.red()*t)), + (int)((b.green()*(1-t)) + (shade.green()*t)), + (int)((b.blue()*(1-t)) + (shade.blue()*t)) + ); + + cgNew.setColor(QColorGroup::Base, b); + } + + QListViewItem::paintCell( painter, cgNew, column, width, align ); + } + else + QListViewItem::paintCell( painter, cg, column, width, align ); +} + +int KateFileListItem::compare ( QListViewItem * i, int col, bool ascending ) const +{ + if ( i->rtti() == RTTI_KateFileListItem ) + { + switch( ((KateFileList*)listView())->sortType() ) + { + case KateFileList::sortByID: + { + + int d = (int)doc->documentNumber() - ((KateFileListItem*)i)->documentNumber(); + return ascending ? d : -d; + break; + } + case KateFileList::sortByURL: + return doc->url().prettyURL().compare( ((KateFileListItem*)i)->document()->url().prettyURL() ); + break; + default: + return QListViewItem::compare( i, col, ascending ); + } + } + return 0; +} +//END KateFileListItem + +//BEGIN KFLConfigPage +KFLConfigPage::KFLConfigPage( QWidget* parent, const char *name, KateFileList *fl ) + : Kate::ConfigPage( parent, name ), + m_filelist( fl ), + m_changed( false ) +{ + QVBoxLayout *lo1 = new QVBoxLayout( this ); + int spacing = KDialog::spacingHint(); + lo1->setSpacing( spacing ); + + QGroupBox *gb = new QGroupBox( 1, Qt::Horizontal, i18n("Background Shading"), this ); + lo1->addWidget( gb ); + + QWidget *g = new QWidget( gb ); + QGridLayout *lo = new QGridLayout( g, 2, 2 ); + lo->setSpacing( KDialog::spacingHint() ); + cbEnableShading = new QCheckBox( i18n("&Enable background shading"), g ); + lo->addMultiCellWidget( cbEnableShading, 1, 1, 0, 1 ); + + kcbViewShade = new KColorButton( g ); + lViewShade = new QLabel( kcbViewShade, i18n("&Viewed documents' shade:"), g ); + lo->addWidget( lViewShade, 2, 0 ); + lo->addWidget( kcbViewShade, 2, 1 ); + + kcbEditShade = new KColorButton( g ); + lEditShade = new QLabel( kcbEditShade, i18n("&Modified documents' shade:"), g ); + lo->addWidget( lEditShade, 3, 0 ); + lo->addWidget( kcbEditShade, 3, 1 ); + + // sorting + QHBox *hbSorting = new QHBox( this ); + lo1->addWidget( hbSorting ); + lSort = new QLabel( i18n("&Sort by:"), hbSorting ); + cmbSort = new QComboBox( hbSorting ); + lSort->setBuddy( cmbSort ); + QStringList l; + l << i18n("Opening Order") << i18n("Document Name") << i18n("URL"); + cmbSort->insertStringList( l ); + + lo1->insertStretch( -1, 10 ); + + QWhatsThis::add( cbEnableShading, i18n( + "When background shading is enabled, documents that have been viewed " + "or edited within the current session will have a shaded background. " + "The most recent documents have the strongest shade.") ); + QWhatsThis::add( kcbViewShade, i18n( + "Set the color for shading viewed documents.") ); + QWhatsThis::add( kcbEditShade, i18n( + "Set the color for modified documents. This color is blended into " + "the color for viewed files. The most recently edited documents get " + "most of this color.") ); + + QWhatsThis::add( cmbSort, i18n( + "Set the sorting method for the documents.") ); + + reload(); + + slotEnableChanged(); + connect( cbEnableShading, SIGNAL(toggled(bool)), this, SLOT(slotMyChanged()) ); + connect( cbEnableShading, SIGNAL(toggled(bool)), this, SLOT(slotEnableChanged()) ); + connect( kcbViewShade, SIGNAL(changed(const QColor&)), this, SLOT(slotMyChanged()) ); + connect( kcbEditShade, SIGNAL(changed(const QColor&)), this, SLOT(slotMyChanged()) ); + connect( cmbSort, SIGNAL(activated(int)), this, SLOT(slotMyChanged()) ); +} + +void KFLConfigPage::apply() +{ + if ( ! m_changed ) + return; + m_changed = false; + + // Change settings in the filelist + m_filelist->m_viewShade = kcbViewShade->color(); + m_filelist->m_editShade = kcbEditShade->color(); + m_filelist->m_enableBgShading = cbEnableShading->isChecked(); + m_filelist->setSortType( cmbSort->currentItem() ); + // repaint the affected items + m_filelist->triggerUpdate(); +} + +void KFLConfigPage::reload() +{ + // read in from config file + KConfig *config = kapp->config(); + config->setGroup( "Filelist" ); + cbEnableShading->setChecked( config->readBoolEntry("Shading Enabled", &m_filelist->m_enableBgShading ) ); + kcbViewShade->setColor( config->readColorEntry("View Shade", &m_filelist->m_viewShade ) ); + kcbEditShade->setColor( config->readColorEntry("Edit Shade", &m_filelist->m_editShade ) ); + cmbSort->setCurrentItem( m_filelist->sortType() ); + m_changed = false; +} + +void KFLConfigPage::slotEnableChanged() +{ + kcbViewShade->setEnabled( cbEnableShading->isChecked() ); + kcbEditShade->setEnabled( cbEnableShading->isChecked() ); + lViewShade->setEnabled( cbEnableShading->isChecked() ); + lEditShade->setEnabled( cbEnableShading->isChecked() ); +} + +void KFLConfigPage::slotMyChanged() +{ + m_changed = true; + slotChanged(); +} + +//END KFLConfigPage + + +// kate: space-indent on; indent-width 2; replace-tabs on; |