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.
355 lines
11 KiB
355 lines
11 KiB
/** -*- C++ -*-
|
|
@file adept/application.cpp
|
|
@author Peter Rockai <me@mornfall.net>
|
|
*/
|
|
|
|
#include <tqprocess.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdelocale.h>
|
|
#include <tdeapplication.h>
|
|
#include <kstatusbar.h>
|
|
#include <kdebug.h>
|
|
|
|
#include <apt-front/init.h>
|
|
#include <apt-front/cache/component/packages.h>
|
|
#include <apt-front/cache/component/state.h>
|
|
|
|
#include <adept/commitprogress.h>
|
|
#include <adept/application.h>
|
|
#include <adept/packageinfo.h>
|
|
#include <adept/progress.h>
|
|
#include <adept/utils.h>
|
|
|
|
#ifdef Q_MOC_RUN
|
|
#define KUBUNTU
|
|
#endif
|
|
|
|
namespace adept {
|
|
using namespace cache;
|
|
|
|
#ifdef KUBUNTU
|
|
#include <tqstringlist.h>
|
|
#define DPKG_FIXER_ARGS TQStringList::split(TQString(" "), TQString("dpkg --configure -a"), false)
|
|
|
|
DpkgFixer::DpkgFixer(struct Application* parent)
|
|
: m_parent(parent)
|
|
{
|
|
m_fixer = 0;
|
|
m_waiter = 0;
|
|
m_output = "";
|
|
m_done = false;
|
|
}
|
|
|
|
DpkgFixer::~DpkgFixer()
|
|
{
|
|
if (m_fixer != 0) {
|
|
delete m_fixer;
|
|
}
|
|
if (m_waiter != 0) {
|
|
delete m_waiter;
|
|
}
|
|
|
|
std::cout << "Got output " << m_output.latin1() << std::endl;
|
|
}
|
|
|
|
void DpkgFixer::fixDpkgLock()
|
|
{
|
|
kdDebug() << "Asking user if they would like to fix dpkg lock..." << endl;
|
|
int decision = KMessageBox::warningYesNoCancel(m_parent->mainWindow(),
|
|
i18n("Another process is using the packaging system database "
|
|
"(probably some other Adept application or apt-get or "
|
|
"aptitude).\nWould you like to attempt to resolve this problem? "
|
|
"No will enter read-only mode and Cancel to quit and resolve "
|
|
"this issue yourself."),
|
|
i18n( "Database Locked" ) );
|
|
switch (decision) {
|
|
case KMessageBox::Yes:
|
|
kdDebug() << "User opted to fix the dpkg database. Trying to run the process..." << endl;
|
|
cache::Global::get().close();
|
|
// Call the dpkg fixer.
|
|
m_fixer = new TQProcess(dynamic_cast<TQObject*>(this));
|
|
m_fixer->setArguments(DPKG_FIXER_ARGS);
|
|
|
|
// Handle when the process exits
|
|
connect(dynamic_cast<TQObject*>(m_fixer), TQT_SIGNAL( processExited() ),
|
|
dynamic_cast<TQObject*>(this), TQT_SLOT( retryOpen() ));
|
|
|
|
// Handle when the process has stdout output
|
|
connect(dynamic_cast<TQObject*>(m_fixer), TQT_SIGNAL( readyReadStdout() ),
|
|
dynamic_cast<TQObject*>(this), TQT_SLOT( handleStdout() ));
|
|
|
|
// Handle when the process has stderr output
|
|
connect(dynamic_cast<TQObject*>(m_fixer), TQT_SIGNAL( readyReadStderr() ),
|
|
dynamic_cast<TQObject*>(this), TQT_SLOT( handleStderr() ));
|
|
|
|
// Fire off the waiter...
|
|
m_waiter = new KProgressDialog(m_parent->mainWindow(), "waiter",
|
|
i18n("Unlocking; Please Wait..."), i18n("Unlocking dpkg database; Please wait..."));
|
|
m_waiter->setAllowCancel(false);
|
|
m_waiter->show();
|
|
|
|
m_fixer->start();
|
|
kdDebug() << "dpkg fixer fired off." << endl;
|
|
|
|
break;
|
|
|
|
case KMessageBox::Cancel:
|
|
kdDebug() << "User opted to cancel and repair manually." << endl;
|
|
exit(1);
|
|
break;
|
|
|
|
default:
|
|
kdDebug() << "User opted to continue in read-only mode." << endl;
|
|
m_parent->updateStatusbar();
|
|
m_parent->cacheOpenedNowFinishInit();
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void DpkgFixer::retryOpen()
|
|
{
|
|
kdDebug() << "Retrying the open..." << endl;
|
|
m_waiter->setLabel(i18n("Reopening the dpkg database..."));
|
|
m_waiter->progressBar()->setValue(50);
|
|
try {
|
|
if (!m_fixer->normalExit()) {
|
|
kdDebug() << "The fixer command did not exit normally. Throwing exception." << endl;
|
|
throw 0;
|
|
}
|
|
|
|
kdDebug() << "The fixer command exited normally, trying to reopen the database." << endl;
|
|
cache::Global::get().open( m_parent->openFlags() );
|
|
} catch (...) {
|
|
KMessageBox::information(m_parent->mainWindow(),
|
|
i18n( "Failed to unlock the database. "
|
|
"Please try to resolve this issue. "
|
|
"`sudo dpkg --configure -a` may help." ),
|
|
i18n( "Unlock Failed." ) );
|
|
exit( 1 );
|
|
}
|
|
|
|
m_waiter->progressBar()->setValue(100);
|
|
m_waiter->close();
|
|
m_parent->updateStatusbar();
|
|
m_parent->cacheOpenedNowFinishInit();
|
|
}
|
|
|
|
void DpkgFixer::outputUpdated()
|
|
{
|
|
}
|
|
|
|
void DpkgFixer::handleStdout()
|
|
{
|
|
// m_output += m_fixer->readStdout();
|
|
// outputUpdated();
|
|
}
|
|
|
|
void DpkgFixer::handleStderr()
|
|
{
|
|
// m_output += m_fixer->readStderr();
|
|
// outputUpdated();
|
|
}
|
|
#endif // KUBUNTU
|
|
|
|
Application::Application()
|
|
: m_acceptReadOnly( false ), m_main( 0 ), m_history( 0 ), m_statusBar( 0 )
|
|
{
|
|
#ifdef KUBUNTU
|
|
m_dpkgfixer = 0;
|
|
#endif // KUBUNTU
|
|
}
|
|
|
|
Application::~Application()
|
|
{
|
|
#ifdef KUBUNTU
|
|
if (m_dpkgfixer != 0) {
|
|
delete m_dpkgfixer;
|
|
}
|
|
#endif // KUBUNTU
|
|
}
|
|
|
|
void Application::openCache( unsigned flags )
|
|
{
|
|
m_flags = flags;
|
|
bool ro = m_acceptReadOnly;
|
|
bool root = ::getuid() == 0 || ::geteuid() == 0;
|
|
|
|
try {
|
|
cache::Global::get().open( m_flags );
|
|
} catch (...) {
|
|
try {
|
|
cache::Global::get().open( m_flags | Cache::OpenReadOnly );
|
|
if ( ro && root ) {
|
|
#ifndef KUBUNTU
|
|
kdDebug() << "ro && root -- Database locked." << endl;
|
|
KMessageBox::information(
|
|
m_main, i18n(
|
|
"You will not be able to change your system settings "
|
|
"in any way (install, remove or upgrade software), "
|
|
"because another process is using the packaging system database "
|
|
"(probably some other Adept application or apt-get or "
|
|
"aptitude). Please close the other application before "
|
|
"using this one." ),
|
|
i18n( "Read Only mode: Database Locked" ) );
|
|
#else
|
|
kdDebug() << "Firing off the Kubuntu dpkg database lock fixer..." << endl;
|
|
m_dpkgfixer = new DpkgFixer(this);
|
|
m_dpkgfixer->fixDpkgLock();
|
|
return;
|
|
#endif // KUBUNTU
|
|
} else if ( !root && ro ) {
|
|
kdDebug() << "!root && ro -- Need root privileges." << endl;
|
|
KMessageBox::information(
|
|
m_main, i18n(
|
|
"You will not be able to change your system settings "
|
|
"in any way (install, remove or upgrade software), "
|
|
"because this application needs special administrator "
|
|
"(root) privileges. Please run it as root or "
|
|
"through tdesu or sudo programs to be able to perform "
|
|
"these actions" ),
|
|
i18n( "Read Only mode: Need root privileges" ) );
|
|
} else if ( root && !ro ) {
|
|
#ifndef KUBUNTU
|
|
kdDebug() << "root && !ro -- Database locked." << endl;
|
|
KMessageBox::information(m_main,
|
|
i18n("Another process is using the packaging system database "
|
|
"(probably some other Adept application or apt-get or "
|
|
"aptitude). Please close the other application before "
|
|
"using this one." ),
|
|
i18n( "Read Only mode: Database Locked" ) );
|
|
#else
|
|
kdDebug() << "Firing off the Kubuntu dpkg database lock fixer..." << endl;
|
|
m_dpkgfixer = new DpkgFixer(this);
|
|
m_dpkgfixer->fixDpkgLock();
|
|
return;
|
|
#endif // KUBUNTU
|
|
} else if ( !root && !ro ) {
|
|
kdDebug() << "!root && !ro -- Needs root privileges." << endl;
|
|
KMessageBox::information(
|
|
m_main, i18n( "This application needs special administrator "
|
|
"(root) privileges. Please run it as root or "
|
|
"through tdesu or sudo programs" ),
|
|
i18n( "Need root privileges" ) );
|
|
}
|
|
if ( !ro ) {
|
|
kdDebug() << "cannot continue, exiting" << endl;
|
|
exit( 1 );
|
|
}
|
|
} catch (...) {
|
|
KMessageBox::sorry(
|
|
m_main, i18n(
|
|
"The APT Database could not be opened!"
|
|
" This may be caused by incorrect APT configuration"
|
|
" or some similar problem. Try running apt-setup and"
|
|
" apt-get update in terminal and see if it helps"
|
|
" to resolve the problem." ), i18n( "Could not open cache" ));
|
|
exit( 1 );
|
|
}
|
|
}
|
|
|
|
updateStatusbar();
|
|
cacheOpenedNowFinishInit();
|
|
}
|
|
|
|
void Application::initHistory() {
|
|
cache::Global::get().addComponent(
|
|
m_history = new History() );
|
|
}
|
|
|
|
void Application::initKDEDebconf()
|
|
{
|
|
// xxx unhardcode the package name somehow?
|
|
if (cache::Global::get().packages()
|
|
.packageByName( "libqt-perl" ).isInstalled())
|
|
putenv( "DEBIAN_FRONTEND=kde" );
|
|
}
|
|
|
|
void Application::initialize()
|
|
{
|
|
CommitProgress::initSystem();
|
|
aptFront::init();
|
|
openCache();
|
|
}
|
|
|
|
void Application::cacheOpenedNowFinishInit() {
|
|
initKDEDebconf();
|
|
initHistory();
|
|
observeComponent< component::State >();
|
|
|
|
initFinished();
|
|
}
|
|
|
|
void Application::checkpoint() {
|
|
if ( !history() ) return;
|
|
setHistoryEnabled( false );
|
|
history()->checkpoint();
|
|
setHistoryEnabled( true );
|
|
}
|
|
|
|
void Application::undo() {
|
|
if ( !history() ) return;
|
|
setHistoryEnabled( false );
|
|
history()->undo();
|
|
setHistoryEnabled( true );
|
|
}
|
|
|
|
void Application::redo() {
|
|
if ( !history() ) return;
|
|
setHistoryEnabled( false );
|
|
history()->redo();
|
|
setHistoryEnabled( true );
|
|
}
|
|
|
|
TQString Application::changeString() {
|
|
component::State &s = cache().state();
|
|
return i18n( " Install %1, upgrade %2, remove %3 " )
|
|
.arg( s.newInstallCount() ).arg( s.upgradeCount() )
|
|
.arg( s.removeCount() );
|
|
}
|
|
|
|
TQString Application::statusString() {
|
|
component::State &s = cache().state();
|
|
return i18n( " %1 installed, %2 upgradable, %3 available " )
|
|
.arg( s.installedCount() ).arg( s.upgradableCount() )
|
|
.arg( s.availableCount() );
|
|
}
|
|
|
|
TQString Application::sizesString() {
|
|
TQString dl = cache().state().downloadSizeString();
|
|
TQString inst = cache().state().installSizeString();
|
|
return i18n( " download: %1, installation: %2 " ).arg( dl ).arg( inst );
|
|
}
|
|
|
|
void Application::setStatusBar( KStatusBar *s ) {
|
|
m_statusBar = s;
|
|
if ( s ) {
|
|
s->message( i18n( "Initializing..." ) );
|
|
s->insertItem( u8( "" ), 0 );
|
|
s->insertItem( u8( "" ), 1 );
|
|
s->insertItem( u8( "" ), 2 );
|
|
adjustFontSize( s, -1 );
|
|
|
|
adept::Progress *pr = new adept::Progress();
|
|
pr->setStatusBar( s );
|
|
cache::Global::get().setProgress( pr );
|
|
}
|
|
}
|
|
|
|
void Application::notifyPostChange( component::Base * )
|
|
{
|
|
updateStatusbar();
|
|
}
|
|
|
|
void Application::updateStatusbar()
|
|
{
|
|
if ( m_statusBar ) {
|
|
m_statusBar->changeItem( changeString(), 0 );
|
|
m_statusBar->changeItem( statusString(), 1 );
|
|
m_statusBar->changeItem( sizesString(), 2 );
|
|
}
|
|
}
|
|
|
|
}
|