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.
adept/adept/adept/packagedetails.cpp

274 lines
9.1 KiB

#include <qtoolbutton.h>
#include <qtextbrowser.h>
#include <qlabel.h>
#include <klocale.h>
#include <kiconloader.h>
#include <qpushbutton.h>
#include <ktoolbar.h>
#include <ktoolbarbutton.h>
#include <kfileitem.h>
#include <kfiledetailview.h>
#include <kapplication.h>
#include <adept/lister.h>
#include <adept/tagchooser.h>
#include <adept/packageinfo.h>
#include <adept/packagedetails.h>
#include <adept/utils.h>
#include <adept/changelog.h>
#include <fstream>
using namespace adept;
ItemChangelog* global_changelog = new ItemChangelog();
PackageDetails::PackageDetails( QWidget *w, const char *n )
: PackageDetailsUi( w, n ),
m_thread( 0 ),
m_qtMutex( true ),
m_logicalAct( 0 ), m_removeAct( 0 ),
m_fileListRunning( false )
{
m_toolbar->setIconSize( 22 );
m_toolbar->setIconText( KToolBar::IconTextRight );
m_toolbar->insertButton( u8( "back" ), BBack, false, i18n( "Back" ) );
m_toolbar->insertButton( u8( "forward" ), BForward, false, i18n( "Forward" ) );
m_toolbar->insertLineSeparator();
m_toolbar->insertButton( u8( "" ), BShow, true, i18n( "Show List" ) );
m_tags->setTitle( i18n( "Assigned Tags" ) );
m_lister->setRangeProvider( this ); // wee
// m_lister->setOpenToplevel( true );
m_description->setPaper( QBrush( colorGroup().background() ) );
connect( m_toolbar->getButton( BShow ), SIGNAL( clicked() ),
this, SIGNAL( showList() ) );
connect( m_toolbar->getButton( BBack ), SIGNAL( clicked() ),
this, SIGNAL( back() ) );
connect( m_toolbar->getButton( BForward ), SIGNAL( clicked() ),
this, SIGNAL( forward() ) );
connect( m_lister, SIGNAL( detailsRequested( Lister::Entity ) ),
this, SIGNAL( detailsRequested( Lister::Entity ) ) );
observeComponent< component::State >();
adjustFontSize( m_name, 1 );
Cache &c = cache::Global::get( m_cache );
component::Packages::iterator i = c.packages().packagesBegin();
while ( !i->hasVersion() ) ++i; // ha hum...
setPackage( *i );
}
Lister::Range PackageDetails::listerRange() {
utils::Range< entity::Relation > r = m_package.depends();
utils::VectorRange< entity::Entity > vr;
while ( r != r.end() ) {
if ( !r->targetPackages().empty() )
std::cerr << r->targetPackages()->name() << std::endl;
vr.consume( *r );
r = r.next();
}
return vr.sorted();
}
void PackageDetails::loadFileListWorker()
{
entity::Package p = m_package;
std::string fl, flfile = "/var/lib/dpkg/info/" + p.name() + ".list";
std::ifstream ifl( flfile.c_str() );
int i = 0;
kdDebug() << "PackageDetails::loadFileListWorker() entering loop" << endl;
while ( ifl.is_open() && !ifl.eof() ) {
std::string line;
getline( ifl, line );
if ( line == "/." || line == "" )
continue; // nasty evil thing go away
m_qtMutex.lock();
KURL url( "file:///" );
url.addPath( u8( line ) );
KFileItem *it = new KFileItem( url, u8( "" ), 0 );
it->setName( u8( line ) );
m_fileList->insertItem( it );
++i;
m_qtMutex.unlock();
}
kdDebug() << "PackageDetails::loadFileListWorker() leaving loop" << endl;
ifl.close();
}
void PackageDetails::notifyPreRebuild( component::Base * ) {
kdDebug() << "PackageDetails::notifyPreRebuild()" << endl;
Threads::wait();
m_logical->setEnabled( false );
m_remove->setEnabled( false );
m_logical->disconnect( SIGNAL( clicked() ) );
m_remove->disconnect( SIGNAL( clicked() ) );
delete m_logicalAct;
delete m_removeAct;
kdDebug() << "PackageDetails::notifyPreRebuild() done" << endl;
}
void PackageDetails::loadFileList() {
Cache &c = cache::Global::get( m_cache );
if ( m_fileListRunning || !c.isOpen() ) {
QTimer::singleShot( 100, this, SLOT( loadFileList() ) );
return;
}
kdDebug() << "PackageDetails::loadFileList()" << endl;
m_fileListRunning = true;
// the following call is neccessary to invoke buildDefaultType of KMimeType
// the first time the method is called it will check for
// existence of application/octet-stream and *popup a dialog* if
// not found -- we don't want that to happen in a non-gui thread
KMimeType::defaultMimeTypePtr();
m_thread = asyncCall( std::mem_fun( &PackageDetails::loadFileListWorker ), this );
m_qtMutex.lock();
m_fileList->KFileView::clear();
c.progress().OverallProgress( 0, 0, 0, i18n( "Loading filelist..." ) );
m_qtMutex.unlock();
Threads::enqueue( m_thread, &m_qtMutex );
Threads::wait();
c.progress().Done();
m_fileListRunning = false;
kdDebug() << "PackageDetails::loadFileList() finished" << endl;
}
void PackageDetails::setPackage( cache::entity::Package p )
{
kdDebug() << "PackageDetails::setPackage()" << endl;
m_package = p.stable();
m_name->setText( QString( "<b>" ) +
p.name( std::string( "No package" ) ) + "</b>" );
m_info->setPackage( p );
QString l = u8( p.longDescription(
std::string( i18n( "No long description available" ).local8Bit() ) ) );
m_description->setText( QString( "<qt>" )
+ formatLongDescription( l ) + "</qt>" );
std::string na = u8( i18n( "not available" ) );
m_tags->setTags( p.tags( entity::Package::TagSet() ) );
m_tags->openToplevel();
m_architecture->setText( labelFormat( i18n( "Architecture: " ),
p.architecture( na ) ) );
m_filename->setText( labelFormat( i18n( "Filename: " ), p.fileName( na ) ) );
m_md5->setText( labelFormat( i18n( "MD5: " ), p.md5sum( na ) ) );
m_source->setText( labelFormat( i18n( "Source Package: " ), p.source( na ) ) );
/* IF IT ISN'T KUBUNTU, DON'T SUPPORT CHANGELOGS! */
#ifdef KUBUNTU
// Lets go ahead and stick the changelog in there....
try {
global_changelog->setParent(p);
m_changelog->setText(i18n("Loading..."));
connect(dynamic_cast<QObject*>(global_changelog), SIGNAL( changelogReady(QString) ),
dynamic_cast<QObject*>(this), SLOT( changelogDisplay(QString) ));
connect(dynamic_cast<QObject*>(this), SIGNAL( requestTheChangelog() ),
dynamic_cast<QObject*>(global_changelog), SIGNAL( changelogNeeded() ));
emit requestTheChangelog();
} catch (...) {};
#endif /* KUBUNTU */
notifyPostChange( 0 );
m_lister->cleanRebuild();
loadFileList();
}
void PackageDetails::changelogDisplay( QString content ) {
m_changelog->setText(content);
}
void PackageDetails::notifyPostChange( cache::component::Base * )
{
kdDebug() << "PackageDetails::notifyPostChange()" << endl;
// without the timer to break it, there could be a loop where
// we connect the clicked() signal to a slot which would be
// invoked right away when we return -> evil
QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
}
void PackageDetails::notifyPostRebuild( cache::component::Base *b )
{
kdDebug() << "PackageDetails::notifyPostRebuild( " << b << " )" << endl;
// can't call directly because stable entities are not guaranteed
// to be stabilised at this point yet
QTimer::singleShot( 0, this, SLOT( updateLogical() ) );
QTimer::singleShot( 0, this, SLOT( loadFileList() ) );
m_lister->cleanRebuild();
}
void PackageDetails::updateLogical()
{
Cache &c = cache::Global::get( m_cache );
if ( !c.isOpen() ) {
QTimer::singleShot( 100, this, SLOT( updateLogical() ) );
return;
}
kdDebug() << "PackageDetails::updateLogical()" << endl;
entity::Package p = m_package;
kdDebug() << "PackageDetails::updateLogical: p = " << p.name()
<< " p.component() = " << &p.component() << endl;
if ( !p.valid() ) return; // nothing to update
EntityActor *a = 0, *b = 0;
if ( p.canUpgrade() ) {
a = new EntityActor( p.upgrade() );
} else if ( p.canInstall() ) {
a = new EntityActor( p.install() );
} else if ( p.canKeep() ) {
a = new EntityActor( p.keep() );
}
if ( p.canRemove() ) {
b = new EntityActor( p.remove() );
}
if ( a ) {
m_logical->setEnabled( true );
m_logical->setText( u8( a->actor().prettyName() ) );
connect( m_logical, SIGNAL( clicked() ),
a, SLOT( destructiveAct() ) );
} else {
m_logical->setText( i18n( "Install" ) );
m_logical->setEnabled( false );
}
if ( b ) {
m_remove->setEnabled( true );
m_remove->setText( u8( b->actor().prettyName() ) );
connect( m_remove, SIGNAL( clicked() ),
b, SLOT( destructiveAct() ) );
} else {
m_remove->setText( i18n( "Remove" ) );
m_remove->setEnabled( false );
}
m_logicalAct = a;
m_removeAct = b;
// std::copy( r, r.last(), vr );
// r.consume( utils::upcastRange< entity::Entity >( p.depends() ) );
}
void PackageDetails::setHasForward( bool e ) {
m_toolbar->setItemEnabled( BForward, e );
// m_forward->setEnabled( e );
}
void PackageDetails::setHasBack( bool e ) {
m_toolbar->setItemEnabled( BBack, e );
// m_back->setEnabled( e );
}