You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdesdk/kbugbuster/gui/centralwidget.cpp

506 lines
17 KiB

/*
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 <tqsplitter.h>
#include <tqpushbutton.h>
#include <tqwidgetstack.h>
#include <tqlayout.h>
#include <kdialog.h>
#include <kdebug.h>
#include <kcombobox.h>
#include <tdelistview.h>
#include <kinputdialog.h>
#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 <tdefiledialog.h>
#include <tdemessagebox.h>
#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<int> sizes = m_vertSplitter->sizes();
TQValueList<int>::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<BugDetails::Attachment> attachments = details.extractAttachments();
if ( !attachments.isEmpty() )
{
TQStringList fileList;
for ( TQValueList<BugDetails::Attachment>::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<BugDetails::Attachment>::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"