/* centralwidget.cpp - Central widget for the KBB main window 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 #include "kbbprefs.h" #include "bugsystem.h" #include "packagelvi.h" #include "buglvi.h" #include "msginputdialog.h" #include "packageselectdialog.h" #include "cwbugdetails.h" #include "bugcommand.h" #include "severityselectdialog.h" #include "cwsearchwidget.h" #include "cwbuglistcontainer.h" #include "cwbugdetailscontainer.h" #include "bugserver.h" #include "centralwidget.h" #include #include #include "loadallbugsdlg.h" using namespace KBugBusterMainWindow; CentralWidget::CentralWidget( const TQCString &initialPackage, const TQCString &initialComponent, const TQCString &initialBug, TQWidget *parent, const char * name ) : TQWidget( parent, name ) { // Master layout ( new TQVBoxLayout( this, 0, KDialog::spacingHint() ) )->setAutoAdd( true ); // Create TQSplitter children m_vertSplitter = new TQSplitter( Qt::Vertical, this ); m_listPane = new CWBugListContainer( m_vertSplitter ); m_horSplitter = new TQSplitter( Qt::Horizontal,m_vertSplitter ); // The search pane isn't used. Should we remove the code? m_searchPane = new CWSearchWidget( m_horSplitter ); m_bugPane = new CWBugDetailsContainer( m_horSplitter ); m_searchPane->hide(); // m_listPane->hide(); m_searchPane->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum, TQSizePolicy::Minimum ) ); m_horSplitter->setResizeMode( m_searchPane, TQSplitter::FollowSizeHint ); connect( m_listPane, TQT_SIGNAL( resetProgressBar() ), TQT_SIGNAL( resetProgressBar() ) ); connect( m_bugPane, TQT_SIGNAL( resetProgressBar() ), TQT_SIGNAL( resetProgressBar() ) ); // Start the proper jobs for loading the package lists connect( BugSystem::self(), TQT_SIGNAL( packageListAvailable( const Package::List & ) ), TQT_SLOT( updatePackageList( const Package::List & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( bugListAvailable( const Package &, const TQString &, const Bug::List & ) ), TQT_SLOT( updateBugList( const Package &, const TQString &, const Bug::List & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( bugListAvailable( const TQString &, const Bug::List & ) ), TQT_SLOT( updateBugList( const TQString &, const Bug::List & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( bugDetailsAvailable( const Bug &, const BugDetails & ) ), TQT_SLOT( updateBugDetails( const Bug &, const BugDetails & ) ) ); connect( BugSystem::self(), TQT_SIGNAL( loadingError( const TQString & ) ), TQT_SLOT( showLoadingError( const TQString & ) ) ); connect( m_bugPane, TQT_SIGNAL( signalCloseBug() ), TQT_SLOT( closeBug() ) ); connect( m_bugPane, TQT_SIGNAL( signalCloseBugSilently() ), TQT_SLOT( closeBugSilently() ) ); connect( m_bugPane, TQT_SIGNAL( signalReopenBug() ), TQT_SLOT( reopenBug() ) ); connect( m_bugPane, TQT_SIGNAL( signalReassignBug() ), TQT_SLOT( reassignBug() ) ); connect( m_bugPane, TQT_SIGNAL( signalTitleBug() ), TQT_SLOT( titleBug() ) ); connect( m_bugPane, TQT_SIGNAL( signalSeverityBug() ), TQT_SLOT( severityBug() ) ); connect( m_bugPane, TQT_SIGNAL( signalReplyBug() ), TQT_SLOT( replyBug() ) ); connect( m_bugPane, TQT_SIGNAL( signalReplyPrivateBug() ), TQT_SLOT( replyPrivateBug() ) ); connect( m_bugPane, TQT_SIGNAL( signalClearCommand() ), TQT_SLOT( clearCommand() ) ); // Add the selection slots for the listviews connect( m_searchPane->m_searchPackages, TQT_SIGNAL( activated( const TQString & ) ), TQT_SLOT( slotRetrieveBugList( const TQString & ) ) ); connect( m_listPane, TQT_SIGNAL( executed( const Bug & ) ), TQT_SLOT( slotRetrieveBugDetails( const Bug & ) ) ); connect( m_listPane, TQT_SIGNAL( currentChanged( const Bug & ) ), TQT_SLOT( slotSetActiveBug( const Bug & ) ) ); connect( m_listPane, TQT_SIGNAL( searchPackage() ), TQT_SIGNAL( searchPackage() ) ); connect( m_bugPane, TQT_SIGNAL( searchBugNumber() ), TQT_SIGNAL( searchBugNumber() ) ); m_bLoadingAllBugs = false; initialize( initialPackage, initialComponent, initialBug ); } CentralWidget::~CentralWidget() { // kdDebug() << "CentralWidget::~CentralWidget()" << endl; } void CentralWidget::initialize( const TQString& p, const TQString &c, const TQString& b ) { // kdDebug() << "CentralWidget::initialize(): package: '" << p // << "' bug: '" << b << "'" << endl; BugServerConfig cfg = BugSystem::self()->server()->serverConfig(); TQString package = p.isEmpty() ? cfg.currentPackage() : p; TQString bug = b.isEmpty() ? cfg.currentBug() : b; TQString component = c.isEmpty() ? cfg.currentComponent() : c; m_listPane->setNoList(); m_bugPane->setNoBug(); BugSystem::self()->retrievePackageList(); if ( !package.isEmpty() ) { m_currentPackage = BugSystem::self()->package( package ); m_currentComponent = component; BugSystem::self()->retrieveBugList( m_currentPackage, m_currentComponent ); if ( !bug.isEmpty() ) { m_currentBug = BugSystem::self()->bug( m_currentPackage, m_currentComponent, bug ); BugSystem::self()->retrieveBugDetails( m_currentBug ); } } else { if ( !bug.isEmpty() ) { // ### bad way to instanciating a bug object! doesn't restore details! m_currentBug = Bug::fromNumber( bug ); // bug number specified on cmdline. Is it a problem that we don't have details ? BugSystem::self()->retrieveBugDetails( m_currentBug ); } } } void CentralWidget::readConfig() { m_horSplitter->setSizes( KBBPrefs::instance()->mSplitter2 ); m_vertSplitter->setSizes( KBBPrefs::instance()->mSplitter1 ); } void CentralWidget::writeConfig() { #if 0 kdDebug() << "m_vertSplitter" << endl; TQValueList sizes = m_vertSplitter->sizes(); TQValueList::ConstIterator it; for( it = sizes.begin(); it != sizes.end(); ++it ) { kdDebug() << " " << (*it) << endl; } #endif KBBPrefs::instance()->mSplitter1 = m_vertSplitter->sizes(); KBBPrefs::instance()->mSplitter2 = m_horSplitter->sizes(); BugServer *server = BugSystem::self()->server(); server->serverConfig().setCurrentPackage( m_currentPackage.name() ); server->serverConfig().setCurrentComponent( m_currentComponent ); server->serverConfig().setCurrentBug( m_currentBug.number() ); } void CentralWidget::slotRetrieveBugList( const TQString &package ) { slotRetrieveBugList( package, TQString() ); } void CentralWidget::slotRetrieveBugList( const TQString &p, const TQString &component ) { if ( p.isEmpty() ) return; Package package = m_packageList[ p ]; if ( package.isNull() ) { // Invalid package, return return; } if ( ( package == m_currentPackage ) && ( m_currentComponent == component ) ) { return; // Nothing to do } m_currentComponent = component; m_currentPackage = package; BugSystem::self()->retrieveBugList( m_currentPackage, m_currentComponent ); } TQString CentralWidget::currentNumber() const { if( m_currentBug.isNull() ) return ""; else return m_currentBug.number(); } TQString CentralWidget::currentTitle() const { if( m_currentBug.isNull() ) return ""; else return m_currentBug.title(); } void CentralWidget::slotRetrieveBugDetails( const Bug &bug ) { if( m_currentBug == bug ) return; // Nothing to do m_currentBug = bug; BugSystem::self()->retrieveBugDetails( m_currentBug ); } void CentralWidget::slotSetActiveBug( const Bug &bug ) { if( bug.isNull() ) { return; } if( m_activeBug == bug ) return; // Nothing to do m_activeBug = bug; } void CentralWidget::updatePackageList( const Package::List &pkgs ) { // ### needs proper implementation ;-) m_searchPane->m_searchPackages->clear(); m_searchPane->m_searchPackages->completionObject()->clear(); // m_bugPane->m_bugDetails->m_bugPackage->clear(); emit resetProgressBar(); Package::List::ConstIterator it = pkgs.begin(); for ( ; it != pkgs.end(); ++it ) { m_packageList[ ( *it ).name() ] = *it; m_searchPane->m_searchPackages->insertItem( ( *it ).name() ); m_searchPane->m_searchPackages-> completionObject()->addItem( ( *it ).name() ); // m_bugPane->m_bugDetails->m_bugPackage->insertItem( ( *it ).name() ); } /* if( m_bugPane->m_bugStack->id( m_bugPane->m_bugStack->visibleWidget() ) != 0 ) { m_bugPane->m_bugDetails->m_bugPackage->setCurrentItem( -1 ); } */ } void CentralWidget::updateBugList( const Package &pkg, const TQString &component, const Bug::List &bugs ) { m_listPane->setBugList( pkg, component, bugs ); } void CentralWidget::updateBugList( const TQString &label, const Bug::List &bugs ) { m_listPane->setBugList( label, bugs ); } void CentralWidget::updateBugDetails( const Bug &bug, const BugDetails &bd ) { if ( !m_bLoadingAllBugs ) m_bugPane->setBug( bug, bd ); } void CentralWidget::slotReloadPackageList() { BugSystem::self()->cache()->invalidatePackageList(); BugSystem::self()->retrievePackageList(); } void CentralWidget::slotReloadPackage() { if (!m_currentPackage.isNull()) { BugSystem::self()->cache()->invalidateBugList( m_currentPackage, m_currentComponent ); BugSystem::self()->retrieveBugList( m_currentPackage, m_currentComponent ); } } void CentralWidget::slotLoadMyBugs() { BugSystem::self()->retrieveMyBugsList(); } void CentralWidget::slotReloadBug() { if (!m_currentBug.isNull()) { BugSystem::self()->cache()->invalidateBugDetails( m_currentBug ); BugSystem::self()->retrieveBugDetails( m_currentBug ); } } void CentralWidget::updatePackage() { if (!m_currentPackage.isNull()) { BugSystem::self()->retrieveBugList( m_currentPackage, m_currentComponent ); } } void CentralWidget::slotExtractAttachments() { if (!m_currentBug.isNull()) { // Grab bug details (i.e. full-text) from cache, then extract attachments from it BugDetails details = BugSystem::self()->cache()->loadBugDetails( m_currentBug ); TQValueList attachments = details.extractAttachments(); if ( !attachments.isEmpty() ) { TQStringList fileList; for ( TQValueList::Iterator it = attachments.begin() ; it != attachments.end() ; ++it ) { // Handle duplicates if ( fileList.contains( (*it).filename ) ) { int n = 2; // looks stupid to have "blah" and "1-blah", start at 2 TQString fn = TQString::number(n) + '-' + (*it).filename; while ( fileList.contains( fn ) ) { ++n; fn = TQString::number(n) + '-' + (*it).filename; } (*it).filename = fn; } fileList += (*it).filename; } int res = KMessageBox::questionYesNoList( this, i18n("Found the following attachments. Save?"), fileList, TQString(), KStdGuiItem::save(), KStdGuiItem::dontSave() ); if ( res == KMessageBox::No ) return; TQString dir = KFileDialog::getExistingDirectory( TQString(), this, i18n("Select Folder Where to Save Attachments") ); if ( !dir.isEmpty() ) { if ( !dir.endsWith( "/" ) ) dir += '/'; for ( TQValueList::Iterator it = attachments.begin() ; it != attachments.end() ; ++it ) { TQString filename = m_currentBug.number() + '-' + (*it).filename; TQFile file( dir + filename ); if ( file.open( IO_WriteOnly ) ) file.writeBlock( (*it).contents ); else kdError() << "Couldn't save attachment to " << filename << endl; file.close(); } } } } } void CentralWidget::mergeBugs() { TQStringList bugNumbers = m_listPane->selectedBugs(); if ( bugNumbers.count() >= 2 ) { BugSystem::self()->queueCommand( new BugCommandMerge( bugNumbers, m_currentPackage ) ); } } void CentralWidget::unmergeBugs() { BugSystem::self()->queueCommand( new BugCommandUnmerge( m_currentBug, m_currentPackage ) ); } void CentralWidget::closeBug() { MsgInputDialog *dlg = new MsgInputDialog( MsgInputDialog::Close, m_currentBug, m_currentPackage, m_bugPane->bugDetailsWidget()->selectedText(), this ); dlg->show(); } void CentralWidget::closeBugSilently() { BugSystem::self()->queueCommand( new BugCommandCloseSilently( m_currentBug, m_currentPackage ) ); } void CentralWidget::reopenBug() { BugSystem::self()->queueCommand( new BugCommandReopen( m_currentBug, m_currentPackage ) ); } void CentralWidget::reassignBug() { PackageSelectDialog *dlg = new PackageSelectDialog( this ); dlg->exec(); dlg->setPackages( BugSystem::self()->packageList() ); BugServerConfig cfg = BugSystem::self()->server()->serverConfig(); dlg->setRecentPackages( cfg.recentPackages() ); Package package = dlg->selectedPackage(); if ( package.isNull() ) { return; } BugSystem::self()->queueCommand( new BugCommandReassign( m_currentBug, package.name(), m_currentPackage ) ); } void CentralWidget::titleBug() { bool ok = false; TQString title = KInputDialog::getText( i18n("Change Bug Title"), i18n( "Please enter a new title:" ), m_currentBug.title(), &ok, this ); if ( ok && !title.isEmpty() ) { BugSystem::self()->queueCommand( new BugCommandRetitle( m_currentBug, title, m_currentPackage ) ); } } void CentralWidget::severityBug() { SeveritySelectDialog *dlg = new SeveritySelectDialog( this ); dlg->setSeverity( m_currentBug.severity() ); int result = dlg->exec(); if ( result == TQDialog::Accepted ) { BugSystem::self()->queueCommand( new BugCommandSeverity( m_currentBug, dlg->selectedSeverityAsString(), m_currentPackage ) ); } } void CentralWidget::replyBug() { MsgInputDialog *dlg = new MsgInputDialog( MsgInputDialog::Reply, m_currentBug, m_currentPackage, m_bugPane->bugDetailsWidget()->selectedText(), this ); dlg->show(); } void CentralWidget::replyPrivateBug() { MsgInputDialog *dlg = new MsgInputDialog( MsgInputDialog::ReplyPrivate, m_currentBug, m_currentPackage, m_bugPane->bugDetailsWidget()->selectedText(), this ); dlg->show(); } void CentralWidget::clearCommand() { BugSystem::self()->clearCommands( m_currentBug.number() ); } void CentralWidget::searchBugByTitle( int options, const TQString& pattern ) { m_listPane->searchBugByTitle( options, pattern ); } void CentralWidget::slotRetrieveAllBugDetails() { m_bLoadingAllBugs = true; // Make a modal dialog to show the progress, and block usage of main window. LoadAllBugsDlg dlg( m_currentPackage, m_currentComponent ); dlg.exec(); m_bLoadingAllBugs = false; } void CentralWidget::showLoadingError( const TQString &text ) { KMessageBox::error( this, text ); } CWBugDetails *CentralWidget::bugDetailsWidget() { return m_bugPane->bugDetailsWidget(); } #include "centralwidget.moc" /* vim: set et ts=4 sw=4 softtabstop=4: */