2 This file is part of Faster Application Manager.
4 Faster Application Manager is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 Faster Application Manager is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with Faster Application Manager. If not, see <http://www.gnu.org/licenses/>.
17 (C) Heikki Holstila 2010
23 #include "aaptinterface.h"
26 #include "repository.h"
27 #include "mainwindow.h"
30 AAptInterface::AAptInterface(QObject* parent = 0) : QObject(parent)
33 iMainWindow = dynamic_cast<MainWindow*>(parent);
38 iNumSelectedPackages = 0;
40 iNeedRepoRefresh = false;
41 iNeedListRefresh = true;
42 iNeedDateRefresh = true;
43 iNeedDpkgRefresh = true;
44 iSkipRefreshListAndDates = false;
46 iProcAptGetUpdate = new QProcess(this);
47 iProcAptGetSimulate = new QProcess(this);
48 iProcAptGetInstall = new QProcess(this);
49 iProcAptGetClean = new QProcess(this);
51 iProcAptGetUpdate->setProcessChannelMode(QProcess::MergedChannels);
52 iProcAptGetSimulate->setProcessChannelMode(QProcess::MergedChannels);
53 iProcAptGetInstall->setProcessChannelMode(QProcess::MergedChannels);
54 iProcAptGetClean->setProcessChannelMode(QProcess::MergedChannels);
56 connect(iProcAptGetUpdate,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetUpdate(QProcess::ProcessError)));
57 connect(iProcAptGetUpdate,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetUpdate(int,QProcess::ExitStatus)));
58 connect(iProcAptGetUpdate,SIGNAL(readyRead()),this,SLOT(uiUpdaterAptGetUpdate()));
60 connect(iProcAptGetInstall,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetInstall(QProcess::ProcessError)));
61 connect(iProcAptGetInstall,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetInstall(int,QProcess::ExitStatus)));
62 connect(iProcAptGetInstall,SIGNAL(readyRead()),this,SLOT(uiUpdaterAptGetInstall()));
64 connect(iProcAptGetSimulate,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetSimulate(QProcess::ProcessError)));
65 connect(iProcAptGetSimulate,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetSimulate(int,QProcess::ExitStatus)));
67 connect(iProcAptGetClean,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetClean(QProcess::ProcessError)));
68 connect(iProcAptGetClean,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetClean(int,QProcess::ExitStatus)));
70 iProcessPackages.clear();
71 iProcessPackagesOrig.clear();
72 iProcessPackageVersions.clear();
74 QDir logdir(KFapmanDir);
75 logdir.mkpath(KFapmanDir);
77 // create custom apt cache dirs if they don't exist
78 QDir d1(KAptListDir + "/partial");
79 d1.mkpath(KAptListDir + "/partial");
81 // clear log on startup
82 QFile logfile(KLogFile);
85 // clear files left from old versions
86 QFile f1("/root/.fapman/dates.cache");
88 QFile f2("/root/.fapman/lastupdate");
94 AAptInterface::~AAptInterface()
96 if( iProcAptGetUpdate->state() != QProcess::NotRunning )
97 iProcAptGetUpdate->kill();
98 if( iProcAptGetSimulate->state() != QProcess::NotRunning )
99 iProcAptGetSimulate->kill();
100 if( iProcAptGetInstall->state() != QProcess::NotRunning )
101 iProcAptGetInstall->kill();
102 if( iProcAptGetClean->state() != QProcess::NotRunning )
103 iProcAptGetClean->kill();
106 void AAptInterface::addQueuedOperation(interfaceMode mode_)
108 iOperationsQueue.append( mode_ );
111 void AAptInterface::setNeedRefresh(int repos, int lists, int dpkg, int dates)
113 if( repos==0 || repos==1 )
114 iNeedRepoRefresh = (bool)repos;
115 if( lists==0 || lists==1 )
116 iNeedListRefresh = (bool)lists;
117 if( dpkg==0 || dpkg==1 )
118 iNeedDpkgRefresh = (bool)dpkg;
119 if( dates==0 || dates==1 )
120 iNeedDateRefresh = (bool)dates;
123 bool AAptInterface::needListOrDateRefresh()
125 if( iNeedListRefresh || iNeedDpkgRefresh || iNeedDateRefresh )
131 bool AAptInterface::run(dimmer* uiDimmer)
133 if( iMode != ModeNone ) {
134 //qDebug() << "Can't run: not ModeNone";
138 if( iOperationsQueue.count() == 0 ) {
139 qDebug() << "Can't run: Queue empty";
143 iUiDimmer = uiDimmer;
144 iQueueMessages.clear();
152 void AAptInterface::runNext()
154 if( iOperationsQueue.count()==0 ) {
165 iMode = iOperationsQueue.takeAt(0);
166 iModeLog.append(iMode);
168 if( iMode == ModeAptGetUpdate ) {
169 if( !startAptGetUpdate() )
170 errorAptGetUpdate( QProcess::FailedToStart );
172 if( iMode == ModeAptGetInstall ) {
173 if( !startAptGetInstall() )
174 errorAptGetInstall( QProcess::FailedToStart );
176 if( iMode == ModeAptGetSimulate ) {
177 if( !startAptGetSimulate() )
178 errorAptGetSimulate( QProcess::FailedToStart );
180 if( iMode == ModeAptGetClean ) {
181 if( !startAptGetClean() )
182 errorAptGetClean( QProcess::FailedToStart );
184 if( iMode == ModeFetchDates )
187 if( iMode == ModeReadPackages )
191 void AAptInterface::cleanAfterRunEach()
199 void AAptInterface::cleanAfterRunAll()
203 iSkipRefreshListAndDates = false;
206 void AAptInterface::cleanAfterError()
209 iOperationsQueue.clear();
210 iProcessPackages.clear();
211 iProcessPackagesOrig.clear();
212 iProcessPackageVersions.clear();
215 bool AAptInterface::running()
217 if( iMode == ModeNone )
222 bool AAptInterface::cancel()
224 // should return false if can't cancel, or terminate the running process (and clear queue) otherwise
225 if( iMode == ModeNone )
232 if( iMode == ModeAptGetUpdate ) {
233 if( iProcAptGetUpdate->state() == QProcess::Running )
234 iProcAptGetUpdate->terminate();
239 iNeedRepoRefresh = true;
242 if( iMode == ModeAptGetSimulate ) {
243 if( iProcAptGetSimulate->state() == QProcess::Running )
244 iProcAptGetSimulate->terminate();
251 if( iMode == ModeAptGetInstall ) {
252 if( iProcAptGetInstall->state() == QProcess::Running )
253 iProcAptGetInstall->terminate();
260 if( iMode == ModeReadPackages ) {
264 if( iMode == ModeFetchDates ) {
271 bool AAptInterface::startAptGetUpdate()
274 iProcAptGetUpdateOutput.clear();
276 if( !this->writeRepositories() )
278 iNeedListRefresh = true;
279 iNeedDpkgRefresh = true;
280 iNeedDateRefresh = true;
283 iUiDimmer->setProgress(0);
284 iUiDimmer->updateText("Updating catalogs");
289 for( int i=0; i<iRepositories.count(); i++ ) {
290 if( iRepositories.at(i) && iRepositories.at(i)->enabled() ) {
292 QStringList comp = iRepositories.at(i)->components().split(' ');
293 iCatalogsTotal += comp.count();
297 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
298 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
299 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
300 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
302 if( http_proxy != "" )
303 env.insert("http_proxy", http_proxy);
304 if( https_proxy != "" )
305 env.insert("https_proxy", https_proxy);
307 iProcAptGetUpdate->setProcessEnvironment(env);
309 QString runBinary = "/usr/bin/apt-get";
310 QStringList runParameters;
311 runParameters << "-q" << "update"
312 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
313 << "-o" << "Dir::State::lists=" + KAptListDir
314 << "-o" << "Dir::Etc::sourceparts=\"\"";
315 logToFile( runBinary + " " + runParameters.join(" ") );
316 iProcAptGetUpdate->start(runBinary,runParameters);
321 bool AAptInterface::startAptGetSimulate()
323 if( iProcessPackages.count()==0 )
328 iUiDimmer->updateText("Reading dependencies");
331 QString runBinary = "/usr/bin/apt-get";
332 QStringList runParameters;
333 runParameters << "-qsy" << "--allow-unauthenticated"
334 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
335 << "-o" << "Dir::State::lists=" + KAptListDir
336 << "-o" << "Dir::Etc::sourceparts=\"\"";
337 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
338 runParameters << "--auto-remove";
339 runParameters << "install";
340 runParameters << iProcessPackages;
342 logToFile( runBinary + " " + runParameters.join(" ") );
343 iProcAptGetSimulate->start(runBinary,runParameters);
348 bool AAptInterface::startAptGetInstall()
350 if( iProcessPackages.count()==0 )
353 iNeedListRefresh = true;
354 iNeedDpkgRefresh = true;
356 iProcAptGetInstallOutput.clear();
358 qDebug() << "running apt-get install";
360 QString runBinary = "/usr/bin/apt-get";
361 QStringList runParameters;
362 runParameters << "-qy" << "--allow-unauthenticated"
363 << "-o" << "DPkg::options::=--force-confnew"
364 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
365 << "-o" << "Dir::State::lists=" + KAptListDir
366 << "-o" << "Dir::Etc::sourceparts=\"\"";
367 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
368 runParameters << "--auto-remove";
369 runParameters << "install";
370 runParameters << iProcessPackagesOrig;
374 for( int i=0; i<iProcessPackages.count(); i++) {
375 if( iProcessPackages.at(i).endsWith('-') )
381 iAptGetDownloadCount = 0;
382 iAptGetInstallCount = 0;
383 iAptGetRemoveCount = 0;
384 iAptGetInstallTotal = inst_count;
385 iAptGetRemoveTotal = remv_count;
386 iAptGetCurrentFileDownloadSize = 0;
387 iAptGetCurrentFileTotalSize = 0;
388 iAptGetCurrentDownloadFileName = "";
389 iProgressCheckTimer = 0;
392 iUpdateSpeed = false;
394 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
395 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
396 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
397 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
399 if( http_proxy != "" )
400 env.insert("http_proxy", http_proxy);
401 if( https_proxy != "" )
402 env.insert("https_proxy", https_proxy);
404 env.insert("DEBIAN_FRONTEND", "noninteractive");
405 iProcAptGetUpdate->setProcessEnvironment(env);
407 logToFile( runBinary + " " + runParameters.join(" ") );
408 iProcAptGetInstall->start(runBinary,runParameters);
413 bool AAptInterface::startAptGetClean()
415 QString runBinary = "/usr/bin/apt-get";
416 QStringList runParameters;
418 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
419 << "-o" << "Dir::State::lists=" + KAptListDir
420 << "-o" << "Dir::Etc::sourceparts=\"\""
424 iUiDimmer->updateText("Cleaning package cache");
427 logToFile( runBinary + " " + runParameters.join(" ") );
428 iProcAptGetClean->start(runBinary,runParameters);
433 QString AAptInterface::setQProcessErrorMessage(QProcess::ProcessError error)
436 logToFile(QString("Cancelled by user - terminating process"));
437 return "Cancelled by user";
439 else if( error == QProcess::FailedToStart )
440 return "Process failed to start";
441 else if( error == QProcess::Crashed )
442 return "Process crashed";
443 else if( error == QProcess::ReadError )
444 return "QProcess read error";
445 else if( error == QProcess::WriteError )
446 return "QProcess write error";
447 else if( error == QProcess::Timedout )
448 return "QProcess timeout error";
449 else if( error == QProcess::UnknownError )
450 return "QProcess unknown error";
452 return "Unknown error";
455 void AAptInterface::errorAptGetUpdate(QProcess::ProcessError error)
457 QString msg = setQProcessErrorMessage(error);
460 iUiDimmer->setProgress(-1);
462 communicateStatusToUi(false, "Error", msg);
464 iNeedRepoRefresh = true;
468 void AAptInterface::errorAptGetSimulate(QProcess::ProcessError error)
470 QString msg = setQProcessErrorMessage(error);
471 iProcessPackages.clear();
472 iProcessPackagesOrig.clear();
473 iProcessPackageVersions.clear();
475 communicateStatusToUi(false, "Error", msg);
480 void AAptInterface::errorAptGetInstall(QProcess::ProcessError error)
482 QString msg = setQProcessErrorMessage(error);
483 iProcessPackages.clear();
484 iProcessPackagesOrig.clear();
485 iProcessPackageVersions.clear();
487 if( iProgressCheckTimer ) {
488 iProgressCheckTimer->stop();
489 delete iProgressCheckTimer;
490 iProgressCheckTimer = 0;
493 iUiDimmer->setProgress(-1);
496 communicateStatusToUi(false, "Error", msg);
501 void AAptInterface::errorAptGetClean(QProcess::ProcessError error)
503 QString msg = setQProcessErrorMessage(error);
505 communicateStatusToUi(false, "Error", msg);
510 QString AAptInterface::finishProcessCommonErrorMessages(QByteArray& output)
512 QString msg = "Unknown error - see the log for details";
514 if( output.contains("Could not get lock") || output.contains("Could not open lock file") ) {
515 msg = "The package management system is locked by another process or permission was denied";
516 } else if( output.contains("E: Unable to fetch some archives") ) {
517 msg = "Failed to fetch packages - Your network connection might be down or your catalogs could be out of date";
518 } else if( output.contains("E: Couldn't find package") ) {
519 msg = "Missing package, see the log for details - Your catalogs might be out of date";
520 } else if( output.contains("E: Broken packages") ) {
521 msg = "Your system has broken packages or you are trying to install conflicting packages. See the log for details.";
522 } else if( output.contains("E: Handler silently failed") ) {
523 msg = "Handler silently failed - This can happen if you try to install from the forbidden user/hidden category";
524 } else if( iTerminated ) {
525 msg = "The operation was cancelled by user";
526 } else if( output.contains("Temporary failure resolving") || output.contains("Could not resolve host") ) {
527 msg = "DNS errors were reported, check your network connection and/or repository configuration";
528 } else if( output.contains("E: dpkg was interrupted") ) {
529 msg = "Your system has partially installed or broken packages. You'll have to fix this manually. Try dpkg --configure -a";
530 } else if( output.contains("dpkg: error processing") || output.contains("Errors were encountered while processing:") ) {
531 msg = "dpkg reported errors while processing a package - see the log for details";
532 } else if( output.contains("E: Unmet dependencies") ) {
533 msg = "Some of your packages have unmet dependencies which could not be fixed. See the log for details.";
534 } else if( output.contains("E: The method driver") ) {
535 msg = "Apt failed to find a suitable method driver. One or more of your repositories might have an invalid URL.";
541 void AAptInterface::finishedAptGetUpdate(int exitCode, QProcess::ExitStatus exitStatus)
543 //QByteArray output = iProcAptGetUpdate->readAllStandardOutput();
544 //logToFile( "Output from last process:\n---\n"+output );
548 iProcAptGetUpdate->close();
553 QString title = "Operation finished";
554 QString msg = "Catalogs updated";
555 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
559 msg = finishProcessCommonErrorMessages(iProcAptGetUpdateOutput);
563 iUiDimmer->setProgress(-1);
565 if( iProcAptGetUpdateOutput.contains("Could not resolve ") || iProcAptGetUpdateOutput.contains("W: Failed to fetch") ||
566 iProcAptGetUpdateOutput.contains("Temporary failure resolving") ) {
569 msg = "Failed to update some or all of the catalogs. Check your network connection and/or repository configuration";
573 iNeedRepoRefresh = false;
575 QFile lastupdate(KLastUpdateFile); // create an empty file and/or update the modification time
576 if( lastupdate.open(QIODevice::WriteOnly) )
579 int pos = iProcAptGetUpdateOutput.indexOf("\nFetched ");
581 msg += "<br>apt-get: ";
582 msg += iProcAptGetUpdateOutput.mid(pos+1, iProcAptGetUpdateOutput.indexOf('\n', pos+1)-pos ).trimmed();
589 iProcAptGetUpdate->close();
590 communicateStatusToUi(success, title, msg);
594 void AAptInterface::finishedAptGetSimulate(int exitCode, QProcess::ExitStatus exitStatus)
596 QByteArray output = iProcAptGetSimulate->readAllStandardOutput();
597 logToFile( "Output from last process:\n---\n"+output );
601 iProcAptGetSimulate->close();
606 QString title = "Operation finished";
608 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
612 msg = finishProcessCommonErrorMessages(output);
615 iProcessPackages.clear();
616 iProcessPackageVersions.clear();
619 QList<QByteArray> lines = output.split('\n');
621 for( int i=0; i<lines.count(); i++)
623 QString s = lines.at(i);
624 if( s.startsWith("Inst ") )
626 iProcessPackages << s.section(' ',1,1);
630 int a1 = s.indexOf('[');
631 int a2 = s.indexOf(']');
632 if( a1!=-1 && a2!=-1 && a2>a1) {
633 vs = s.mid(a1+1, a2-a1-1) + " -> ";
635 int b1 = s.indexOf('(');
636 int b2 = s.indexOf(' ',b1);
637 if( b1!=-1 && b2!=-1 && b2>b1) {
638 vs += s.mid(b1+1, b2-b1-1);
641 iProcessPackageVersions << vs;
643 if( s.startsWith("Remv ") )
645 iProcessPackages << s.section(' ',1,1) + "-";
648 int a1 = s.indexOf('[');
649 int a2 = s.indexOf(']');
650 if( a1!=-1 && a2!=-1 && a2>a1) {
651 vs = s.mid(a1+1, a2-a1-1);
654 iProcessPackageVersions << vs;
661 iProcAptGetSimulate->close();
662 communicateStatusToUi(success, title, msg);
666 void AAptInterface::finishedAptGetInstall(int exitCode, QProcess::ExitStatus exitStatus)
668 //QByteArray output = iProcAptGetInstall->readAllStandardOutput();
669 //logToFile( "Output from last process:\n---\n"+output );
672 iProcAptGetInstall->close();
678 QString title = "Operation finished";
679 QString msg = "Package operations finished successfully";
680 if( exitCode != 0 || exitStatus == QProcess::CrashExit || iTerminated )
684 msg = finishProcessCommonErrorMessages(iProcAptGetInstallOutput);
687 if( iProgressCheckTimer ) {
688 iProgressCheckTimer->stop();
689 delete iProgressCheckTimer;
690 iProgressCheckTimer = 0;
693 iUiDimmer->setProgress(-1);
695 iProcessPackages.clear();
696 iProcessPackagesOrig.clear();
697 iProcessPackageVersions.clear();
702 iProcAptGetInstall->close();
703 communicateStatusToUi(success, title, msg);
707 void AAptInterface::finishedAptGetClean(int exitCode, QProcess::ExitStatus exitStatus)
709 QByteArray output = iProcAptGetClean->readAllStandardOutput();
710 // this should produce no output
711 //logToFile( "Output from last process:\n---\n"+output );
715 iProcAptGetClean->close();
720 QString title = "Operation finished";
721 QString msg = "Package cache cleaned";
722 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
726 msg = finishProcessCommonErrorMessages(output);
731 iProcAptGetClean->close();
732 communicateStatusToUi(success, title, msg);
737 void AAptInterface::uiUpdaterAptGetUpdate()
739 QByteArray data = iProcAptGetUpdate->read( iProcAptGetUpdate->bytesAvailable() );
740 logToFile( data, false );
741 iProcAptGetUpdateOutput.append(data);
746 QStringList lines = QString( data.trimmed() ).split('\n');
748 for( int i=0; i<lines.count(); i++ )
750 if( lines.at(i).startsWith("Get:") || lines.at(i).startsWith("Hit ") )
753 //iUiDimmer->updateText( QString("Updating catalogs (%1)").arg(iCatalogCounter) );
754 //qDebug() << iCatalogCounter << iCatalogsTotal;
755 iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
758 void AAptInterface::uiUpdaterAptGetInstall()
760 QByteArray data = iProcAptGetInstall->read( iProcAptGetInstall->bytesAvailable() );
761 logToFile( data, false );
762 iProcAptGetInstallOutput.append(data);
767 QStringList lines = QString( data.trimmed() ).split('\n');
770 bool resetprogress = true;
772 QString pkgname = "";
774 for( int i=0; i<lines.count(); i++ )
776 QStringList l = lines.at(i).split(' ');
778 if( l.count()>=4 && l.at(0).startsWith("Get:") ) {
779 oper = "Downloading";
782 Package* pkg = iPackagesAvailable.value(pkgname,0);
784 iAptGetCurrentDownloadFileName = pkg->fileName();
785 iAptGetCurrentFileTotalSize = pkg->size()/1024;
786 pkgname += QString(" (%1 kB)").arg(iAptGetCurrentFileTotalSize);
788 iAptGetDownloadCount++;
789 oper += QString(" %1/%2").arg(iAptGetDownloadCount).arg(iAptGetInstallTotal);
791 if( !iProgressCheckTimer ) {
792 iProgressCheckTimer = new QTimer(this);
793 connect(iProgressCheckTimer,SIGNAL(timeout()),this,SLOT(progressCheckTimerCallback()));
794 iProgressCheckTimer->start(500);
796 resetprogress = false;
797 } else if( l.count()>=2 && l.at(0)=="Unpacking") {
799 if( l.count()>=3 && l.at(1)=="replacement" )
803 iAptGetInstallCount++;
804 oper += QString(" %1/%2").arg(iAptGetInstallCount).arg(iAptGetInstallTotal);
806 } else if( l.count()>=3 && l.at(0)=="Setting" && l.at(1)=="up") {
809 } else if( l.count()>=2 && l.at(0)=="Removing") {
812 iAptGetRemoveCount++;
813 oper += QString(" %1/%2").arg(iAptGetRemoveCount).arg(iAptGetRemoveTotal);
815 } else if( l.count()>=1 && l.at(0)=="Done!") {
816 oper = "Setting up...";
821 /* // this does not seem to work, dpkg always dies first
822 if( lines.at(i).startsWith("***") && lines.at(i).contains("(Y/I/N/O/D/Z)") ) {
823 if( iMainWindow->confirmDialog("Overwrite configuration file?","la la la") )
825 iProcAptGetInstall->write("Y\n");
827 iProcAptGetInstall->write("N\n");
833 if( update && iUiDimmer && iUiDimmer->busy() ) {
834 iUiDimmer->updateText( oper + "<br>" + pkgname );
835 if( resetprogress ) {
836 iUiDimmer->setProgress(-1);
837 if( iProgressCheckTimer ) {
838 iProgressCheckTimer->stop();
839 delete iProgressCheckTimer;
840 iProgressCheckTimer = 0;
846 void AAptInterface::progressCheckTimerCallback()
848 if( iAptGetCurrentDownloadFileName=="" )
851 qint64 prevsize = iAptGetCurrentFileDownloadSize;
852 QFile pkgfile(KAptArchivePartialDir + "/" + iAptGetCurrentDownloadFileName);
853 iAptGetCurrentFileDownloadSize = pkgfile.size()/1024;
855 if( iAptGetCurrentFileDownloadSize >= prevsize ) {
856 iSpeedKbpsPrev = iSpeedKbps;
857 iSpeedKbps = (iAptGetCurrentFileDownloadSize-prevsize)*2;
862 iUpdateSpeed = false;
866 if( iUiDimmer && iUiDimmer->busy() ) {
867 int p = iAptGetCurrentFileDownloadSize*100/iAptGetCurrentFileTotalSize;
868 if( iAptGetDownloadCount > 0 && iAptGetCurrentFileDownloadSize==0 )
870 iUiDimmer->setProgress( p );
871 if( iSpeedKbps>=0 && iSpeedKbpsPrev>=0 && iUpdateSpeed ) {
872 iUiDimmer->setDownloadSpeed( (iSpeedKbps+iSpeedKbpsPrev)/2 );
878 void AAptInterface::communicateStatusToUi(bool success, QString title, QString msg)
880 qDebug() << title << msg;
881 iQueueMessages.append(msg);
883 if( iMainWindow && iOperationsQueue.count()==0 )
885 // title comes from the last finished operation only
886 iMainWindow->operationQueueFinished(iModeLog, success, title, iQueueMessages);
890 QByteArray AAptInterface::readLogFile()
895 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
899 QByteArray line = own.readLine();
906 log = "The log is empty";
911 void AAptInterface::logToFile( QString data, bool logtime )
913 logToFile( data.toAscii(), logtime );
916 void AAptInterface::logToFile( QByteArray data, bool logtime )
920 if( f.open( QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text ) )
924 out << "--- " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << " ---\n";
934 void AAptInterface::readRepositoryInfo()
936 for(int i=0; i<iRepositories.count(); i++) {
937 if( iRepositories.at(i) )
938 delete iRepositories.at(i);
940 iRepositories.clear();
941 bool ownFound = false;
943 QFile own( KOwnRepoFile );
944 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
949 QString line = own.readLine().trimmed();
950 if( line.startsWith("deb ") || line.startsWith("#deb ") )
952 r = new Repository();
953 if( r->setFromString(line) ) {
954 iRepositories.append(r);
955 //qDebug() << r->toListFileNames();
962 if( iRepositories.count() > 0 )
966 QFile names( KOwnRepoNamesFile );
967 if( names.open(QIODevice::ReadOnly | QIODevice::Text ) )
970 while(!names.atEnd() && c<iRepositories.count())
972 QString line = names.readLine().trimmed();
973 if( line.trimmed()!="" )
974 iRepositories.at(c)->setName( line.trimmed() );
984 QFile ham( KHamRepoListFile );
985 if( ham.open(QIODevice::ReadOnly | QIODevice::Text ) )
989 QString line = ham.readLine();
990 Repository* r = new Repository();
991 if( r->setFromString(line) ) {
992 iRepositories.append(r);
1001 bool AAptInterface::writeRepositories()
1003 #ifndef Q_WS_MAEMO_5 // for simulator
1007 iNeedListRefresh = true;
1009 QFile own( KOwnRepoFile );
1010 if( own.open(QIODevice::WriteOnly | QIODevice::Text ) )
1012 QTextStream out(&own);
1013 for( int i=0; i<iRepositories.count(); i++ )
1014 out << iRepositories.at(i)->toString() << "\n";
1018 QFile names( KOwnRepoNamesFile );
1019 if( names.open(QIODevice::WriteOnly | QIODevice::Text ) )
1021 QTextStream out(&names);
1022 for( int i=0; i<iRepositories.count(); i++ )
1023 out << iRepositories.at(i)->name() << "\n";
1027 QFile ham( KAptSourceList );
1028 if( ham.open(QIODevice::WriteOnly | QIODevice::Text ) )
1030 QTextStream out(&ham);
1031 for( int i=0; i<iRepositories.count(); i++ )
1032 out << iRepositories.at(i)->toString() << "\n";
1037 qDebug() << "Failed to write repository list!";
1043 bool AAptInterface::needRepoRefresh()
1045 #ifndef Q_WS_MAEMO_5 // for simulator
1049 if( iNeedRepoRefresh || iSettings->qsettings()->value("need_repo_refresh", false).toBool() ) {
1050 iNeedRepoRefresh = false;
1051 iSettings->qsettings()->setValue("need_repo_refresh", false);
1052 qDebug() << "repo update required, debug 1";
1056 QFile own(KAptSourceList);
1060 qDebug() << "repo update required, debug 2";
1064 QFileInfo a(KLastUpdateFile);
1068 aDate = a.lastModified();
1070 qDebug() << "repo update required, debug 3";
1073 aDate = aDate.addSecs(24*60*60); //24h
1075 if( aDate < QDateTime::currentDateTime() ) {
1076 qDebug() << "repo update required, debug 4";
1080 qDebug() << "repo update not required";
1086 void AAptInterface::startPkgListRead()
1088 logToFile( QString("Start reading package lists") );
1089 qDebug() << "reading package list files";
1091 if( !iNeedListRefresh && !iNeedDpkgRefresh ) {
1092 qDebug() << "no need to refresh package lists";
1093 logToFile( QString("No need to read package lists") );
1094 communicateStatusToUi(true, "Operation finished", "Package data already up to date");
1100 iUiDimmer->updateText("Reading package lists<br>");
1101 iUiDimmer->setProgress(0);
1104 // clear packages lists
1105 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1107 QHashIterator<QString, Package*> a( iPackagesAvailable );
1113 iPackagesAvailable.clear();
1116 if( iNeedDpkgRefresh )
1118 QHashIterator<QString, Package*> i( iPackagesInstalled );
1124 iPackagesInstalled.clear();
1127 // read apt database (available packages)
1129 time_aptread.start();
1131 int pkgcount_apt = 0;
1132 QDir dir( KAptListDir );
1133 QFileInfoList files = dir.entryInfoList();
1135 quint64 totaldatasize = 0;
1136 quint64 currentreaddata = 0;
1137 quint64 lastupdatedata = 0;
1138 quint64 updateinterval = 1000000;
1139 if( iNeedListRefresh && !iSkipRefreshListAndDates ) {
1140 for( int i=0; i<files.count(); i++ )
1142 if( files.at(i).fileName().endsWith("_Packages"))
1143 totaldatasize += files.at(i).size();
1146 if( iNeedDpkgRefresh ) {
1147 QFileInfo dbinfo( KDpkgStatusFile );
1148 totaldatasize += dbinfo.size();
1152 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1156 for( int i=0; i<files.count(); i++ )
1158 Repository* currentRepo = 0;
1159 if( files.at(i).absoluteFilePath().endsWith("_Packages") )
1162 for(int x=0; x<iRepositories.count(); x++) {
1163 if( iRepositories.at(x)->toListFileNames().contains( files.at(i).fileName() ) ) {
1164 currentRepo = iRepositories.at(x);
1168 if( iUiDimmer && currentRepo ) {
1169 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">" + currentRepo->name() + "</font>");
1172 //qDebug() << files.at(i).fileName();
1174 QFile db( files.at(i).absoluteFilePath() );
1175 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1176 qDebug() << "FAIL: Unable to read apt database";
1177 communicateStatusToUi(false, "Error", "Unable to read package lists");
1182 while (!db.atEnd() && !iTerminated) {
1183 Package* newpkg = ReadNextPackage(db, currentreaddata);
1184 //qDebug() << "read" << currentreaddata << "of" << totaldatasize;
1185 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1186 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1187 lastupdatedata = currentreaddata;
1188 QApplication::processEvents();
1193 newpkg->addRepository( currentRepo );
1195 Package* exists = iPackagesAvailable.value(newpkg->name(),0);
1197 iPackagesAvailable.insert(newpkg->name(), newpkg);
1199 if( Package::versionCompare(newpkg->version(),exists->version()) )
1201 iPackagesAvailable.remove(exists->name());
1204 iPackagesAvailable.insert(newpkg->name(), newpkg);
1206 if( newpkg->version() == exists->version() ) {
1207 exists->addRepository( currentRepo );
1208 if( newpkg->fullFileNames().count()>0 )
1209 exists->addFullFileName( newpkg->fullFileNames().at(0) );
1211 exists->addFullFileName("unknown_dir/unknown_filename");
1223 qDebug() << "apt database read took" << time_aptread.elapsed() << "ms";
1224 qDebug() << "Processed" << filecount << "package list files";
1228 iUiDimmer->setProgress(-1);
1230 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1234 iNeedListRefresh = false;
1235 iNeedDateRefresh = true;
1238 // read dpkg database (installed packages)
1239 if( iNeedDpkgRefresh )
1242 QTime time_dpkgread;
1243 time_dpkgread.start();
1245 int pkgcount_dpkg = 0;
1246 QFile db( KDpkgStatusFile );
1247 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1248 qDebug() << "FAIL: Unable to read dpkg database";
1249 communicateStatusToUi(false, "Error", "Unable to read package database");
1255 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">dpkg database</font>");
1258 while (!db.atEnd() && !iTerminated) {
1259 Package* newpkg = ReadNextPackage(db, currentreaddata);
1260 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1261 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1262 lastupdatedata = currentreaddata;
1263 QApplication::processEvents();
1267 if( newpkg->isInstalled() ) {
1268 iPackagesInstalled.insert(newpkg->name(), newpkg);
1277 qDebug() << "dpkg database read took" << time_dpkgread.elapsed() << "ms";
1279 qDebug() << "Processed" << pkgcount_apt << "(apt) and" << pkgcount_dpkg << "(dpkg) package entries";
1280 qDebug() << "In DB:" << iPackagesAvailable.count() << "packages available,"
1281 << iPackagesInstalled.count() << "installed";
1285 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1288 iNeedDpkgRefresh = false;
1291 logToFile( QString("Finished reading package lists") );
1293 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">Creating package view</font>");
1294 QApplication::processEvents();
1295 iUiDimmer->setProgress(-1);
1300 communicateStatusToUi(true, "Operation finished", "Package data read");
1305 Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
1307 iMultiLine=MultiLineNone;
1309 Package* pkg = new Package("", this);
1311 bool pkgready = false;
1312 while( !pkgready && !f.atEnd() ) {
1313 QByteArray line = f.readLine();
1314 currentreaddata += line.size();
1315 if( processPackageDataLine(pkg,line) ) {
1320 if( pkg->name() != "" && pkg->isInstalled() ) {
1321 QFileInfo f( KDpkgInfoDir + "/" + pkg->name() + ".list" );
1323 pkg->setDate( f.lastModified() );
1326 pkg->updateStatus();
1328 if( pkg->name() == "" ) {
1335 bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
1337 if( !line.startsWith(' ') && !line.startsWith('\t') )
1338 line = line.trimmed();
1339 if( line.trimmed()=="" )
1342 if( line.startsWith("Package:") )
1344 pkg->setName( line.mid(8).trimmed() );
1345 iMultiLine=MultiLineNone;
1347 else if( line.startsWith("Status:") )
1349 if( line.mid(7).trimmed() == "install ok installed" )
1350 pkg->setInstalled(true);
1352 pkg->setInstalled(false);
1354 else if( line.startsWith("Section:") )
1356 pkg->setSection( line.mid(8).trimmed() );
1358 else if( line.startsWith("Version:") )
1360 pkg->setVersion( line.mid(8).trimmed() );
1362 else if( line.startsWith("Filename:") )
1364 pkg->addFullFileName( line.mid(9).trimmed() );
1366 else if( line.startsWith("Size:") )
1368 pkg->setSize( line.mid(5).trimmed().toInt() );
1370 else if( line.startsWith("Installed-Size:") )
1372 pkg->setInstalledSize( line.mid(15).trimmed().toInt() );
1374 else if( line.startsWith("Maemo-Display-Name:") )
1376 pkg->setMaemoDisplayName( line.mid(19).trimmed() );
1378 else if( line.startsWith("Depends:") )
1380 pkg->appendDepends( line.mid(8).trimmed() );
1382 else if( line.startsWith("Conflicts:") )
1384 pkg->appendConflicts( line.mid(10).trimmed() );
1386 else if( line.startsWith("Pre-Depends:") )
1388 pkg->appendPreDepends( line.mid(12).trimmed() );
1390 else if( line.startsWith("Provides:") )
1392 pkg->appendProvides( line.mid(9).trimmed() );
1394 else if( line.startsWith("Replaces:") )
1396 pkg->appendReplaces( line.mid(9).trimmed() );
1398 else if( line.startsWith("Breaks:") )
1400 pkg->appendBreaks( line.mid(7).trimmed() );
1402 else if( line.startsWith("Recommends:") )
1404 pkg->appendRecommends( line.mid(11).trimmed() );
1406 else if( line.startsWith("Suggests:") )
1408 pkg->appendSuggests( line.mid(9).trimmed() );
1411 if( iMultiLine == MultiLineDesc ) {
1412 if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
1413 if( line.trimmed()!="." )
1414 pkg->appendDescLong( line.trimmed() + "\n" );
1416 pkg->appendDescLong( "\n" );
1418 iMultiLine = MultiLineNone;
1421 else if( iMultiLine == MultiLineIcon ) {
1422 if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
1423 pkg->appendIconData( line.trimmed() );
1425 iMultiLine = MultiLineNone;
1428 else if( iMultiLine == MultiLineUpgradeDesc ) {
1429 if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
1430 pkg->appendUpgradeDescription( line.trimmed() + "\n" );
1432 iMultiLine = MultiLineNone;
1436 if( line.startsWith("Description:") )
1438 pkg->setDescShort( line.mid(12).trimmed() );
1439 iMultiLine = MultiLineDesc;
1441 else if( line.startsWith("Maemo-Icon-26:") )
1443 if( line.mid(15).trimmed() != "" ) {
1444 pkg->appendIconData( line.mid(15).trimmed() );
1446 iMultiLine = MultiLineIcon;
1448 else if( line.startsWith("Maemo-Upgrade-Description:") )
1450 pkg->appendUpgradeDescription( line.mid(26).trimmed() + "\n" );
1451 iMultiLine = MultiLineUpgradeDesc;
1459 void AAptInterface::writeBlacklist()
1461 QHashIterator<QString, Package*> i( iPackagesAvailable );
1466 if( i.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1467 iBlacklist << i.value()->name();
1469 else if( i.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1470 iBlacklist << (i.value()->name() + " " + i.value()->version());
1474 QHashIterator<QString, Package*> j( iPackagesInstalled );
1479 if( j.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1480 iBlacklist << j.value()->name();
1482 else if( j.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1483 iBlacklist << (j.value()->name() + " " + j.value()->version());
1487 iBlacklist.removeDuplicates();
1489 QFile f( KBlacklistFile );
1490 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1492 QTextStream out(&f);
1493 for( int i=0; i<iBlacklist.count(); i++ )
1494 out << iBlacklist.at(i) << "\n";
1498 qDebug() << "blacklist: wrote" << iBlacklist.count() << "entries";
1501 void AAptInterface::readBlacklist()
1503 QFile f( KBlacklistFile );
1504 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1506 while( !f.atEnd() ) {
1507 QString line = f.readLine().trimmed();
1509 iBlacklist.append(line);
1514 iBlacklist.removeDuplicates();
1516 qDebug() << "blacklist: read" << iBlacklist.count() << "entries";
1518 for( int i=0; i<iBlacklist.count(); i++ )
1520 QStringList parts = iBlacklist.at(i).split(' ');
1521 Package* pkg = iPackagesAvailable.value(parts.at(0).trimmed(), 0);
1522 Package* pkg2 = iPackagesInstalled.value(parts.at(0).trimmed(), 0);
1523 if( parts.count()==1 ) {
1525 pkg->setBlacklisted(BlacklistSelect::BlacklistAll);
1527 pkg2->setBlacklisted(BlacklistSelect::BlacklistAll);
1528 } else if( parts.count()==2 ) {
1529 if( pkg && pkg->version()==parts.at(1) )
1530 pkg->setBlacklisted(BlacklistSelect::BlacklistThis);
1531 if( pkg2 && pkg2->version()==parts.at(1) )
1532 pkg2->setBlacklisted(BlacklistSelect::BlacklistThis);
1534 qDebug() << "Warning: invalid blacklist entry:" << iBlacklist.at(i);
1539 void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList oldstate)
1542 qDebug() << "Warning: trying to remove null package from blacklist";
1546 QStringList newlist;
1547 bool removed = false;
1549 for( int i=0; i<iBlacklist.count(); i++ )
1551 if( oldstate == BlacklistSelect::BlacklistAll )
1553 if( !(iBlacklist.at(i) == pkg->name()) ) {
1554 newlist << iBlacklist.at(i);
1555 } else removed = true;
1556 } else if( oldstate == BlacklistSelect::BlacklistThis ) {
1557 if( !(iBlacklist.at(i) == (pkg->name()+" "+pkg->version())) ) {
1558 newlist << iBlacklist.at(i);
1559 } else removed = true;
1564 qDebug() << "blacklist: removed" << pkg->name();
1566 qDebug() << "blacklist:" << pkg->name() << "not in saved list";
1568 iBlacklist = newlist;
1572 void AAptInterface::startFetchDates()
1574 logToFile( QString("Start fetching package dates") );
1575 qDebug() << "start fetching package dates";
1577 if( !iNeedDateRefresh || iSkipRefreshListAndDates ) {
1578 qDebug() << "no need to fetch dates";
1579 logToFile( QString("No need to fetch dates") );
1580 communicateStatusToUi(true, "Operation finished", "Date information already up to date");
1586 iUiDimmer->updateText("Reading date cache");
1587 iUiDimmer->setProgress(0);
1588 QApplication::processEvents();
1594 iUiDimmer->updateText("Fetching package date information");
1595 QApplication::processEvents();
1598 QNetworkAccessManager* nam = new QNetworkAccessManager(this);
1602 int updProgress = 0;
1604 QHash<QString, Package*> fetchable;
1605 QHashIterator<QString, Package*> i( iPackagesAvailable );
1606 while (i.hasNext() )
1609 if( !i.value()->date().isValid() && i.value()->section().startsWith("user/") && !i.value()->isBlacklisted() )
1611 Repository* repo = 0;
1612 for( int x=0; x<i.value()->repositories().count(); x++ ) {
1613 if( i.value()->repositories().at(x) && i.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1615 repo = i.value()->repositories().at(x);
1620 fetchable.insert(i.value()->name(), i.value());
1625 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(dateFetchNetworkReply(QNetworkReply*)));
1626 iDateRequestsWaiting = 0;
1627 iDateRequestsSent = 0;
1628 iDateRequestsReceived = 0;
1629 iNetworkError = QNetworkReply::NoError;
1631 QString dbgcount = QString("need to fetch date for %1 packages").arg(fetchable.count());
1632 qDebug() << dbgcount;
1633 logToFile(dbgcount);
1635 QHashIterator<QString, Package*> fe( fetchable );
1636 while (fe.hasNext() && !iTerminated)
1640 if( updProgress >=10 ) {
1641 iUiDimmer->setProgress( count*100/fetchable.count() );
1645 if( !fe.value()->date().isValid() && fe.value()->section().startsWith("user/") && !fe.value()->isBlacklisted() )
1648 Repository* repo = 0;
1649 QString fullFilename = "unknown_filename";
1650 for( int x=0; x<fe.value()->repositories().count(); x++ ) {
1651 if( fe.value()->repositories().at(x) && fe.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1653 repo = fe.value()->repositories().at(x);
1654 if( fe.value()->fullFileNames().count()>x )
1655 fullFilename = fe.value()->fullFileNames().at(x);
1662 url = repo->url() + repo->dir() + fullFilename + "#" + fe.value()->name();
1664 //qDebug() << "getting date for" << fe.value()->name();
1668 QNetworkRequest r(u);
1670 if( iDateRequestsReceived == 0 ) {
1671 while( iDateRequestsWaiting>0 ) {
1672 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1675 while( iDateRequestsWaiting>50 ) {
1676 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1680 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1681 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1683 qDebug() << "fatal network error, aborting fetch";
1684 logToFile(QString("Fatal network error, date fetch aborted"));
1688 iDateRequestsSent++;
1689 iDateRequestsWaiting++;
1692 count = iDateRequestsReceived;
1696 while( iDateRequestsWaiting>0 ) {
1697 if( updProgress >=10 ) {
1698 iUiDimmer->setProgress( count*100/fetchable.count() );
1701 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1702 count = iDateRequestsReceived;
1707 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1708 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1710 // don't stop on this error, only inform the user
1711 iMainWindow->notifyDialog("Network error", "There was a network error while fetching date information, the fetch was aborted");
1716 iUiDimmer->setProgress(-1);
1718 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1724 iUiDimmer->setProgress(100);
1725 QApplication::processEvents();
1728 QString dbgstr = QString("sent %1 requests, received %2 replies with %3 errors").arg(iDateRequestsSent).arg(iDateRequestsReceived).arg(iDateRequestErrors);
1733 logToFile( QString("Finished fetching package dates") );
1735 if( fetchable.count()>0 || !dateCacheExists() ) {
1736 iUiDimmer->updateText("Writing date cache");
1737 QApplication::processEvents();
1742 iUiDimmer->updateText("Creating package view");
1743 QApplication::processEvents();
1744 iUiDimmer->setProgress(-1);
1747 communicateStatusToUi(true, "Operation finished", "Package dates fetched");
1748 iNeedDateRefresh = false;
1752 void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
1754 iDateRequestsWaiting--;
1755 iDateRequestsReceived++;
1756 //qDebug() << "reply" << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
1757 iNetworkError = reply->error();
1759 if( reply->error() == QNetworkReply::NoError && reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid() )
1761 QString pkgname = reply->url().fragment();
1762 //qDebug() << pkgname;
1764 if( pkgname.isEmpty() )
1765 qDebug() << "warning: empty packagename in reply";
1767 Package* pkg = iPackagesAvailable.value(pkgname, 0);
1769 pkg->setDate( reply->header(QNetworkRequest::LastModifiedHeader).toDateTime() );
1771 qDebug() << "warning: unknown packagename in reply:" << pkgname;
1775 if( reply->error() != QNetworkReply::NoError ) {
1776 QString dbg = reply->url().fragment() + QString(": error %1: ").arg(reply->error()) + reply->errorString();
1779 iDateRequestErrors++;
1781 reply->deleteLater();
1784 void AAptInterface::writeDateCache()
1786 qDebug() << "writing date cache";
1788 QFile f(KDateCacheFile);
1789 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1791 QTextStream out(&f);
1792 QHashIterator<QString, Package*> i( iPackagesAvailable );
1793 while (i.hasNext() )
1796 if( i.value()->date().isValid() && i.value()->section().startsWith("user/") )
1797 out << i.value()->name() << " " << i.value()->version() << " " << i.value()->date().toString(Qt::ISODate) << "\n";
1801 qDebug() << "Warning: failed to write date cache";
1802 logToFile(QString("Failed to write date cache"));
1806 void AAptInterface::readDateCache()
1808 qDebug() << "reading date cache";
1810 QFile f(KDateCacheFile);
1811 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1813 while( !f.atEnd() ) {
1814 QString line = f.readLine().trimmed();
1815 QStringList parts = line.split(' ');
1816 if( parts.count()==3 ) {
1817 Package* pkg = iPackagesAvailable.value(parts.at(0),0);
1818 if( pkg && pkg->section().startsWith("user/") && pkg->version()==parts.at(1) )
1820 QDateTime dt = QDateTime::fromString( parts.at(2), Qt::ISODate);
1821 if( dt.isValid() ) {
1824 qDebug() << "Warning: Invalid date in date cache";
1825 logToFile(QString("Invalid date in date cache"));
1829 qDebug() << "Warning: error in date cache:" << line;
1830 logToFile(QString("Error in date cache"));
1835 qDebug() << "date cache does not exist";
1839 bool AAptInterface::dateCacheExists()
1841 QFileInfo f(KDateCacheFile);
1845 bool AAptInterface::loadInstallFiles(QStringList files_)