/* cwbuglistcontainer.cpp - Container for the bug list copyright : (c) 2001 by Martijn Klingens email : klingens@kde.org ************************************************************************* * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ************************************************************************* */ #include #include #include #include #include #include #include #include #include #if KDE_IS_VERSION( 3, 2, 90 ) #include #endif #include #include "bugsystem.h" #include "cwloadingwidget.h" #include "buglvi.h" #include "kbbprefs.h" #include "kfind.h" #include "cwbuglistcontainer.h" #include using namespace KBugBusterMainWindow; CWBugListContainer::CWBugListContainer( TQWidget *parent , const char * name ) : TQWidget( parent, name ), m_find(0), m_findItem(0) { TQBoxLayout *topLayout = new TQVBoxLayout( this ); topLayout->setSpacing( KDialog::spacingHint() ); topLayout->setMargin( KDialog::marginHint() ); m_listLabel = new TQLabel( this ); topLayout->addWidget( m_listLabel ); topLayout->setStretchFactor( m_listLabel, 0 ); TQFont f = m_listLabel->font(); f.setBold( true ); m_listLabel->setFont( f ); m_listStack = new TQWidgetStack( this ); // Create Outstanding Bugs listview m_listBugs = new TDEListView( m_listStack ); topLayout->addWidget( new TDEListViewSearchLineWidget( m_listBugs, this ) ); topLayout->addWidget( m_listStack ); topLayout->setStretchFactor( m_listStack, 1 ); m_listBugs->addColumn( i18n( "Number" ) ); m_listBugs->addColumn( i18n( "Age" ) ); m_listBugs->addColumn( i18n( "Title" ), 500 ); // so that the widthmode isn't "Maximum" m_listBugs->addColumn( i18n( "Status" ) ); m_listBugs->addColumn( i18n( "Severity" ) ); m_listBugs->addColumn( i18n( "Sender" ), 150 ); // idem. hardcoded widths suck a bit, but... m_listBugs->setAllColumnsShowFocus( true ); m_listBugs->setColumnAlignment( 0, AlignRight ); m_listBugs->setSorting( 0, false ); m_listBugs->setShowSortIndicator( true ); m_listBugs->setSelectionMode( TQListView::Extended ); // needed for merging bugs m_listBugs->restoreLayout( KBBPrefs::instance()->config(), "BugListLayout" ); connect( m_listBugs, TQT_SIGNAL( executed( TQListViewItem * ) ), TQT_SLOT( execute( TQListViewItem * ) ) ); connect( m_listBugs, TQT_SIGNAL( returnPressed( TQListViewItem * ) ), TQT_SLOT( execute( TQListViewItem * ) ) ); connect( m_listBugs, TQT_SIGNAL( currentChanged( TQListViewItem * ) ), TQT_SLOT( changeCurrent( TQListViewItem * ) ) ); // Fill WidgetStack in Outstanding Bugs pane m_listLoading = new CWLoadingWidget( CWLoadingWidget::TopFrame, m_listStack ); connect( m_listLoading, TQT_SIGNAL( clicked() ), TQT_SIGNAL( searchPackage() ) ); m_listStack->addWidget( m_listBugs, 0 ); m_listStack->addWidget( m_listLoading, 1 ); setNoList(); connect( BugSystem::self(), TQT_SIGNAL( bugListLoading( const Package &, const TQString & ) ), TQT_SLOT( setLoading( const Package &, const TQString & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( bugListLoading( const TQString & ) ), TQT_SLOT( setLoading( const TQString & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( bugListCacheMiss( const Package & ) ), TQT_SLOT( setCacheMiss( const Package & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( bugListCacheMiss( const TQString & ) ), TQT_SLOT( setCacheMiss( const TQString & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( commandQueued( BugCommand * ) ), TQT_SLOT( markBugCommand( BugCommand * ) ) ); connect( BugSystem::self(), TQT_SIGNAL( commandCanceled( const TQString & ) ), TQT_SLOT( clearCommand( const TQString & ) ) ); } CWBugListContainer::~CWBugListContainer() { m_listBugs->saveLayout( KBBPrefs::instance()->config(), "BugListLayout" ); KBBPrefs::instance()->writeConfig(); delete m_find; } void CWBugListContainer::setBugList( const TQString &label, const Bug::List &bugs ) { // List pane is invisible by default, make visible show(); m_listBugs->clear(); emit resetProgressBar(); bool showClosed = KBBPrefs::instance()->mShowClosedBugs; bool showWishes = KBBPrefs::instance()->mShowWishes; uint noBugs = 0; uint noWishes = 0; for ( Bug::List::ConstIterator it = bugs.begin(); it != bugs.end(); ++it ) { if ( ( *it ).status() != Bug::Closed || showClosed ) { if ( ( *it ).severity() != Bug::Wishlist || showWishes ) new BugLVI( m_listBugs, *it ); if ( ( *it ).severity() != Bug::Wishlist ) noBugs++; else noWishes++; } } m_listLabel->setText( i18n( "%1 (%2 bugs, %3 wishes)" ).arg( label ).arg( noBugs ).arg( noWishes ) ); m_listStack->raiseWidget( 0 ); } void CWBugListContainer::setBugList( const Package &package, const TQString &component, const Bug::List &bugs ) { TQString listLabel; if ( component.isEmpty() ) { if ( package.components().count() > 1 ) listLabel = i18n( "Product '%1', all components" ).arg( package.name() ); else listLabel = i18n( "Product '%1'" ).arg( package.name() ); } else { listLabel = i18n( "Product '%1', component '%2'" ).arg( package.name(), component ); } setBugList( listLabel, bugs ); } void CWBugListContainer::execute( TQListViewItem *lvi ) { BugLVI *item = dynamic_cast( lvi ); if( !item ) { kdWarning() << "CWBugListContainer::execute() Selected bug " << lvi->text( 0 ) << " is not a BugLVI! Ignoring event." << endl; return; } emit executed( item->bug() ); } void CWBugListContainer::changeCurrent( TQListViewItem *lvi ) { if( !lvi ) { emit currentChanged( Bug() ); return; } BugLVI *item = dynamic_cast( lvi ); if( !item ) { kdWarning() << "CWBugListContainer::changeCurrent() Selected bug " << lvi->text( 0 ) << " is not a BugLVI! Ignoring event." << endl; return; } emit currentChanged( item->bug() ); } void CWBugListContainer::setNoList() { m_listLabel->setText( i18n("Outstanding Bugs") ); m_listLoading->setText( i18n( "Click here to select a product" ) ); m_listStack->raiseWidget( 1 ); } void CWBugListContainer::setLoading( const Package &package, const TQString &component ) { if ( component.isEmpty() ) setLoading( i18n( "Retrieving List of Outstanding Bugs for Product '%1'..." ).arg( package.name() ) ); else setLoading( i18n( "Retrieving List of Outstanding Bugs for Product '%1' (Component %2)..." ).arg( package.name(), component ) ); } void CWBugListContainer::setLoading( const TQString &label ) { m_listLoading->setText( label ); m_listStack->raiseWidget( 1 ); } void CWBugListContainer::setCacheMiss( const Package &package ) { setCacheMiss( i18n( "Package '%1'" ).arg( package.name() ) ); } void CWBugListContainer::setCacheMiss( const TQString &label ) { m_listLoading->setText( i18n( "%1 is not available offline." ).arg( label ) ); m_listStack->raiseWidget( 1 ); } void CWBugListContainer::markBugCommand( BugCommand *cmd ) { BugLVI *item = (BugLVI *)m_listBugs->firstChild(); while( item ) { if ( item->bug().number() == cmd->bug().number() ) { item->setCommandState( BugCommand::Queued ); break; } item = (BugLVI *)item->nextSibling(); } m_listBugs->triggerUpdate(); } void CWBugListContainer::clearCommand( const TQString &bug ) { BugLVI *item = (BugLVI *)m_listBugs->firstChild(); while( item ) { if ( item->bug().number() == bug ) { item->setCommandState( BugCommand::None ); break; } item = (BugLVI *)item->nextSibling(); } m_listBugs->triggerUpdate(); } void CWBugListContainer::searchBugByTitle( int options, const TQString& pattern ) { m_find = new KFind( pattern, options, this ); // Connect signals to code which handles highlighting // of found text. connect(m_find, TQT_SIGNAL( highlight( const TQString &, int, int ) ), this, TQT_SLOT( searchHighlight( const TQString &, int, int ) ) ); connect(m_find, TQT_SIGNAL( findNext() ), this, TQT_SLOT( slotFindNext() ) ); m_findItem = (BugLVI *)m_listBugs->firstChild(); if ( options & KFindDialog::FromCursor && m_listBugs->currentItem() ) m_findItem = (BugLVI *)m_listBugs->currentItem(); slotFindNext(); } // Note: if a 'find next' action is added, then one should also ensure // that m_findItem never becomes dangling (i.e. clear it when clearing the listview). void CWBugListContainer::slotFindNext() { KFind::Result res = KFind::NoMatch; while( res == KFind::NoMatch && m_findItem ) { if ( m_find->needData() ) m_find->setData( m_findItem->text(2) ); // Let KFind inspect the text fragment, and display a dialog if a match is found res = m_find->find(); if ( res == KFind::NoMatch ) { if ( m_find->options() & KFindDialog::FindBackwards ) m_findItem = (BugLVI *)m_findItem->itemAbove(); else m_findItem = (BugLVI *)m_findItem->itemBelow(); } } if ( res == KFind::NoMatch ) // i.e. at end if ( m_find->shouldRestart() ) { m_findItem = (BugLVI *)m_listBugs->firstChild(); slotFindNext(); } else { delete m_find; m_find = 0L; } } void CWBugListContainer::searchHighlight( const TQString &, int, int ) { if ( m_findItem ) { m_listBugs->clearSelection(); m_listBugs->setSelected( m_findItem, true ); m_listBugs->ensureItemVisible( m_findItem ); } } TQStringList CWBugListContainer::selectedBugs() const { TQStringList lst; BugLVI *item = (BugLVI *)m_listBugs->firstChild(); while( item ) { if ( item->isSelected() ) lst.append( item->bug().number() ); item = (BugLVI *)item->nextSibling(); } return lst; } #include "cwbuglistcontainer.moc" /* vim: set et ts=4 sw=4 softtabstop=4: */