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;
45 iLastListUpdate.setTime_t(0);
46 iLastDpkgUpdate.setTime_t(0);
48 iProcAptGetUpdate = new QProcess(this);
49 iProcAptGetSimulate = new QProcess(this);
50 iProcAptGetInstall = new QProcess(this);
51 iProcAptGetClean = new QProcess(this);
53 iProcAptGetUpdate->setProcessChannelMode(QProcess::MergedChannels);
54 iProcAptGetSimulate->setProcessChannelMode(QProcess::MergedChannels);
55 iProcAptGetInstall->setProcessChannelMode(QProcess::MergedChannels);
56 iProcAptGetClean->setProcessChannelMode(QProcess::MergedChannels);
58 connect(iProcAptGetUpdate,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetUpdate(QProcess::ProcessError)));
59 connect(iProcAptGetUpdate,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetUpdate(int,QProcess::ExitStatus)));
60 connect(iProcAptGetUpdate,SIGNAL(readyRead()),this,SLOT(uiUpdaterAptGetUpdate()));
62 connect(iProcAptGetInstall,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetInstall(QProcess::ProcessError)));
63 connect(iProcAptGetInstall,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetInstall(int,QProcess::ExitStatus)));
64 connect(iProcAptGetInstall,SIGNAL(readyRead()),this,SLOT(uiUpdaterAptGetInstall()));
66 connect(iProcAptGetSimulate,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetSimulate(QProcess::ProcessError)));
67 connect(iProcAptGetSimulate,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetSimulate(int,QProcess::ExitStatus)));
69 connect(iProcAptGetClean,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetClean(QProcess::ProcessError)));
70 connect(iProcAptGetClean,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetClean(int,QProcess::ExitStatus)));
72 iProcessPackages.clear();
73 iProcessPackagesOrig.clear();
74 iProcessPackageVersions.clear();
76 QDir logdir(KFapmanDir);
77 logdir.mkpath(KFapmanDir);
79 // create custom apt cache dirs if they don't exist
80 QDir d1(KAptListDir + "/partial");
81 d1.mkpath(KAptListDir + "/partial");
83 // clear log on startup
84 QFile logfile(KLogFile);
87 // clear files left from old versions
88 QFile f1("/root/.fapman/dates.cache");
90 QFile f2("/root/.fapman/lastupdate");
96 AAptInterface::~AAptInterface()
98 if( iProcAptGetUpdate->state() != QProcess::NotRunning )
99 iProcAptGetUpdate->kill();
100 if( iProcAptGetSimulate->state() != QProcess::NotRunning )
101 iProcAptGetSimulate->kill();
102 if( iProcAptGetInstall->state() != QProcess::NotRunning )
103 iProcAptGetInstall->kill();
104 if( iProcAptGetClean->state() != QProcess::NotRunning )
105 iProcAptGetClean->kill();
108 void AAptInterface::addQueuedOperation(interfaceMode mode_)
110 iOperationsQueue.append( mode_ );
113 void AAptInterface::setNeedRefresh(int repos, int lists, int dpkg, int dates)
115 if( repos==0 || repos==1 )
116 iNeedRepoRefresh = (bool)repos;
117 if( lists==0 || lists==1 )
118 iNeedListRefresh = (bool)lists;
119 if( dpkg==0 || dpkg==1 )
120 iNeedDpkgRefresh = (bool)dpkg;
121 if( dates==0 || dates==1 )
122 iNeedDateRefresh = (bool)dates;
125 bool AAptInterface::needListOrDateRefresh()
127 if( iNeedListRefresh || iNeedDpkgRefresh || iNeedDateRefresh )
133 bool AAptInterface::run(dimmer* uiDimmer)
135 if( iMode != ModeNone ) {
136 //qDebug() << "Can't run: not ModeNone";
140 if( iOperationsQueue.count() == 0 ) {
141 qDebug() << "Can't run: Queue empty";
145 iUiDimmer = uiDimmer;
146 iQueueMessages.clear();
154 void AAptInterface::runNext()
156 if( iOperationsQueue.count()==0 ) {
167 iMode = iOperationsQueue.takeAt(0);
168 iModeLog.append(iMode);
170 if( iMode == ModeAptGetUpdate ) {
171 if( !startAptGetUpdate() )
172 errorAptGetUpdate( QProcess::FailedToStart );
174 if( iMode == ModeAptGetInstall ) {
175 if( !startAptGetInstall() )
176 errorAptGetInstall( QProcess::FailedToStart );
178 if( iMode == ModeAptGetSimulate ) {
179 if( !startAptGetSimulate() )
180 errorAptGetSimulate( QProcess::FailedToStart );
182 if( iMode == ModeAptGetClean ) {
183 if( !startAptGetClean() )
184 errorAptGetClean( QProcess::FailedToStart );
186 if( iMode == ModeFetchDates )
189 if( iMode == ModeReadPackages )
193 void AAptInterface::cleanAfterRunEach()
201 void AAptInterface::cleanAfterRunAll()
205 iSkipRefreshListAndDates = false;
208 void AAptInterface::cleanAfterError()
211 iOperationsQueue.clear();
212 iProcessPackages.clear();
213 iProcessPackagesOrig.clear();
214 iProcessPackageVersions.clear();
217 bool AAptInterface::running()
219 if( iMode == ModeNone )
224 bool AAptInterface::cancel()
226 // should return false if can't cancel, or terminate the running process (and clear queue) otherwise
227 if( iMode == ModeNone )
234 if( iMode == ModeAptGetUpdate ) {
235 if( iProcAptGetUpdate->state() == QProcess::Running )
236 iProcAptGetUpdate->terminate();
241 iNeedRepoRefresh = true;
244 if( iMode == ModeAptGetSimulate ) {
245 if( iProcAptGetSimulate->state() == QProcess::Running )
246 iProcAptGetSimulate->terminate();
253 if( iMode == ModeAptGetInstall ) {
254 if( iProcAptGetInstall->state() == QProcess::Running )
255 iProcAptGetInstall->terminate();
262 if( iMode == ModeReadPackages ) {
266 if( iMode == ModeFetchDates ) {
273 bool AAptInterface::startAptGetUpdate()
276 iProcAptGetUpdateOutput.clear();
278 if( !this->writeRepositories() )
280 iNeedListRefresh = true;
281 iNeedDpkgRefresh = true;
282 iNeedDateRefresh = true;
285 iUiDimmer->setProgress(0);
286 iUiDimmer->updateText("Updating catalogs");
291 for( int i=0; i<iRepositories.count(); i++ ) {
292 if( iRepositories.at(i) && iRepositories.at(i)->enabled() ) {
294 QStringList comp = iRepositories.at(i)->components().split(' ');
295 iCatalogsTotal += comp.count();
299 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
300 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
301 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
302 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
304 if( http_proxy != "" )
305 env.insert("http_proxy", http_proxy);
306 if( https_proxy != "" )
307 env.insert("https_proxy", https_proxy);
309 iProcAptGetUpdate->setProcessEnvironment(env);
311 QString runBinary = "/usr/bin/apt-get";
312 QStringList runParameters;
313 runParameters << "-q" << "update"
314 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
315 << "-o" << "Dir::State::lists=" + KAptListDir
316 << "-o" << "Dir::Etc::sourceparts=\"\"";
317 logToFile( runBinary + " " + runParameters.join(" ") );
318 iProcAptGetUpdate->start(runBinary,runParameters);
323 bool AAptInterface::startAptGetSimulate()
325 if( iProcessPackages.count()==0 )
330 iUiDimmer->updateText("Reading dependencies");
333 QString runBinary = "/usr/bin/apt-get";
334 QStringList runParameters;
335 runParameters << "-qsy" << "--allow-unauthenticated"
336 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
337 << "-o" << "Dir::State::lists=" + KAptListDir
338 << "-o" << "Dir::Etc::sourceparts=\"\"";
339 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
340 runParameters << "--auto-remove";
341 runParameters << "install";
342 runParameters << iProcessPackages;
344 logToFile( runBinary + " " + runParameters.join(" ") );
345 iProcAptGetSimulate->start(runBinary,runParameters);
350 bool AAptInterface::startAptGetInstall()
352 if( iProcessPackages.count()==0 )
355 iNeedListRefresh = true;
356 iNeedDpkgRefresh = true;
358 iProcAptGetInstallOutput.clear();
360 qDebug() << "running apt-get install";
362 QString runBinary = "/usr/bin/apt-get";
363 QStringList runParameters;
364 runParameters << "-qy" << "--allow-unauthenticated"
365 << "-o" << "DPkg::options::=--force-confnew"
366 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
367 << "-o" << "Dir::State::lists=" + KAptListDir
368 << "-o" << "Dir::Etc::sourceparts=\"\"";
369 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
370 runParameters << "--auto-remove";
371 runParameters << "install";
372 runParameters << iProcessPackagesOrig;
376 for( int i=0; i<iProcessPackages.count(); i++) {
377 if( iProcessPackages.at(i).endsWith('-') )
383 iAptGetDownloadCount = 0;
384 iAptGetInstallCount = 0;
385 iAptGetRemoveCount = 0;
386 iAptGetInstallTotal = inst_count;
387 iAptGetRemoveTotal = remv_count;
388 iAptGetCurrentFileDownloadSize = 0;
389 iAptGetCurrentFileTotalSize = 0;
390 iAptGetCurrentDownloadFileName = "";
391 iProgressCheckTimer = 0;
394 iUpdateSpeed = false;
396 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
397 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
398 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
399 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
401 if( http_proxy != "" )
402 env.insert("http_proxy", http_proxy);
403 if( https_proxy != "" )
404 env.insert("https_proxy", https_proxy);
406 env.insert("DEBIAN_FRONTEND", "noninteractive");
407 iProcAptGetUpdate->setProcessEnvironment(env);
409 logToFile( runBinary + " " + runParameters.join(" ") );
410 iProcAptGetInstall->start(runBinary,runParameters);
415 bool AAptInterface::startAptGetClean()
417 QString runBinary = "/usr/bin/apt-get";
418 QStringList runParameters;
420 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
421 << "-o" << "Dir::State::lists=" + KAptListDir
422 << "-o" << "Dir::Etc::sourceparts=\"\""
426 iUiDimmer->updateText("Cleaning package cache");
429 logToFile( runBinary + " " + runParameters.join(" ") );
430 iProcAptGetClean->start(runBinary,runParameters);
435 QString AAptInterface::setQProcessErrorMessage(QProcess::ProcessError error)
438 logToFile(QString("Cancelled by user - terminating process"));
439 return "Cancelled by user";
441 else if( error == QProcess::FailedToStart )
442 return "Process failed to start";
443 else if( error == QProcess::Crashed )
444 return "Process crashed";
445 else if( error == QProcess::ReadError )
446 return "QProcess read error";
447 else if( error == QProcess::WriteError )
448 return "QProcess write error";
449 else if( error == QProcess::Timedout )
450 return "QProcess timeout error";
451 else if( error == QProcess::UnknownError )
452 return "QProcess unknown error";
454 return "Unknown error";
457 void AAptInterface::errorAptGetUpdate(QProcess::ProcessError error)
459 QString msg = setQProcessErrorMessage(error);
462 iUiDimmer->setProgress(-1);
464 communicateStatusToUi(false, "Error", msg);
466 iNeedRepoRefresh = true;
470 void AAptInterface::errorAptGetSimulate(QProcess::ProcessError error)
472 QString msg = setQProcessErrorMessage(error);
473 iProcessPackages.clear();
474 iProcessPackagesOrig.clear();
475 iProcessPackageVersions.clear();
477 communicateStatusToUi(false, "Error", msg);
482 void AAptInterface::errorAptGetInstall(QProcess::ProcessError error)
484 QString msg = setQProcessErrorMessage(error);
485 iProcessPackages.clear();
486 iProcessPackagesOrig.clear();
487 iProcessPackageVersions.clear();
489 if( iProgressCheckTimer ) {
490 iProgressCheckTimer->stop();
491 delete iProgressCheckTimer;
492 iProgressCheckTimer = 0;
495 iUiDimmer->setProgress(-1);
498 communicateStatusToUi(false, "Error", msg);
503 void AAptInterface::errorAptGetClean(QProcess::ProcessError error)
505 QString msg = setQProcessErrorMessage(error);
507 communicateStatusToUi(false, "Error", msg);
512 QString AAptInterface::finishProcessCommonErrorMessages(QByteArray& output)
514 QString msg = "Unknown error - see the log for details";
516 if( output.contains("Could not get lock") || output.contains("Could not open lock file") ) {
517 msg = "The package management system is locked by another process or permission was denied";
518 } else if( output.contains("E: Unable to fetch some archives") ) {
519 msg = "Failed to fetch packages - Your network connection might be down or your catalogs could be out of date";
520 } else if( output.contains("E: Couldn't find package") ) {
521 msg = "Missing package, see the log for details - Your catalogs might be out of date";
522 } else if( output.contains("E: Broken packages") ) {
523 msg = "Your system has broken packages or you are trying to install conflicting packages. See the log for details.";
524 } else if( output.contains("E: Handler silently failed") ) {
525 msg = "Handler silently failed - This can happen if you try to install from the forbidden user/hidden category";
526 } else if( iTerminated ) {
527 msg = "The operation was cancelled by user";
528 } else if( output.contains("Temporary failure resolving") || output.contains("Could not resolve host") ) {
529 msg = "DNS errors were reported, check your network connection and/or repository configuration";
530 } else if( output.contains("E: dpkg was interrupted") ) {
531 msg = "Your system has partially installed or broken packages. You'll have to fix this manually. Try dpkg --configure -a";
532 } else if( output.contains("dpkg: error processing") || output.contains("Errors were encountered while processing:") ) {
533 msg = "dpkg reported errors while processing a package - see the log for details";
534 } else if( output.contains("E: Unmet dependencies") ) {
535 msg = "Some of your packages have unmet dependencies which could not be fixed. See the log for details.";
536 } else if( output.contains("E: The method driver") ) {
537 msg = "Apt failed to find a suitable method driver. One or more of your repositories might have an invalid URL.";
543 void AAptInterface::finishedAptGetUpdate(int exitCode, QProcess::ExitStatus exitStatus)
545 //QByteArray output = iProcAptGetUpdate->readAllStandardOutput();
546 //logToFile( "Output from last process:\n---\n"+output );
550 iProcAptGetUpdate->close();
555 QString title = "Operation finished";
556 QString msg = "Catalogs updated";
557 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
561 msg = finishProcessCommonErrorMessages(iProcAptGetUpdateOutput);
565 iUiDimmer->setProgress(-1);
567 if( iProcAptGetUpdateOutput.contains("Could not resolve ") || iProcAptGetUpdateOutput.contains("W: Failed to fetch") ||
568 iProcAptGetUpdateOutput.contains("Temporary failure resolving") ) {
571 msg = "Failed to update some or all of the catalogs. Check your network connection and/or repository configuration";
575 iNeedRepoRefresh = false;
577 QFile lastupdate(KLastUpdateFile); // create an empty file and/or update the modification time
578 if( lastupdate.open(QIODevice::WriteOnly) )
581 int pos = iProcAptGetUpdateOutput.indexOf("\nFetched ");
583 msg += "<br>apt-get: ";
584 msg += iProcAptGetUpdateOutput.mid(pos+1, iProcAptGetUpdateOutput.indexOf('\n', pos+1)-pos ).trimmed();
591 iProcAptGetUpdate->close();
592 communicateStatusToUi(success, title, msg);
596 void AAptInterface::finishedAptGetSimulate(int exitCode, QProcess::ExitStatus exitStatus)
598 QByteArray output = iProcAptGetSimulate->readAllStandardOutput();
599 logToFile( "Output from last process:\n---\n"+output );
603 iProcAptGetSimulate->close();
608 QString title = "Operation finished";
610 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
614 msg = finishProcessCommonErrorMessages(output);
617 iProcessPackages.clear();
618 iProcessPackageVersions.clear();
621 QList<QByteArray> lines = output.split('\n');
623 for( int i=0; i<lines.count(); i++)
625 QString s = lines.at(i);
626 if( s.startsWith("Inst ") )
628 iProcessPackages << s.section(' ',1,1);
632 int a1 = s.indexOf('[');
633 int a2 = s.indexOf(']');
634 if( a1!=-1 && a2!=-1 && a2>a1) {
635 vs = s.mid(a1+1, a2-a1-1) + " -> ";
637 int b1 = s.indexOf('(');
638 int b2 = s.indexOf(' ',b1);
639 if( b1!=-1 && b2!=-1 && b2>b1) {
640 vs += s.mid(b1+1, b2-b1-1);
643 iProcessPackageVersions << vs;
645 if( s.startsWith("Remv ") )
647 iProcessPackages << s.section(' ',1,1) + "-";
650 int a1 = s.indexOf('[');
651 int a2 = s.indexOf(']');
652 if( a1!=-1 && a2!=-1 && a2>a1) {
653 vs = s.mid(a1+1, a2-a1-1);
656 iProcessPackageVersions << vs;
663 iProcAptGetSimulate->close();
664 communicateStatusToUi(success, title, msg);
668 void AAptInterface::finishedAptGetInstall(int exitCode, QProcess::ExitStatus exitStatus)
670 //QByteArray output = iProcAptGetInstall->readAllStandardOutput();
671 //logToFile( "Output from last process:\n---\n"+output );
674 iProcAptGetInstall->close();
680 QString title = "Operation finished";
681 QString msg = "Package operations finished successfully";
682 if( exitCode != 0 || exitStatus == QProcess::CrashExit || iTerminated )
686 msg = finishProcessCommonErrorMessages(iProcAptGetInstallOutput);
689 if( iProgressCheckTimer ) {
690 iProgressCheckTimer->stop();
691 delete iProgressCheckTimer;
692 iProgressCheckTimer = 0;
695 iUiDimmer->setProgress(-1);
697 iProcessPackages.clear();
698 iProcessPackagesOrig.clear();
699 iProcessPackageVersions.clear();
704 iProcAptGetInstall->close();
705 communicateStatusToUi(success, title, msg);
709 void AAptInterface::finishedAptGetClean(int exitCode, QProcess::ExitStatus exitStatus)
711 QByteArray output = iProcAptGetClean->readAllStandardOutput();
712 // this should produce no output
713 //logToFile( "Output from last process:\n---\n"+output );
717 iProcAptGetClean->close();
722 QString title = "Operation finished";
723 QString msg = "Package cache cleaned";
724 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
728 msg = finishProcessCommonErrorMessages(output);
733 iProcAptGetClean->close();
734 communicateStatusToUi(success, title, msg);
739 void AAptInterface::uiUpdaterAptGetUpdate()
741 QByteArray data = iProcAptGetUpdate->read( iProcAptGetUpdate->bytesAvailable() );
742 logToFile( data, false );
743 iProcAptGetUpdateOutput.append(data);
748 QStringList lines = QString( data.trimmed() ).split('\n');
750 for( int i=0; i<lines.count(); i++ )
752 if( lines.at(i).startsWith("Get:") || lines.at(i).startsWith("Hit ") )
755 //iUiDimmer->updateText( QString("Updating catalogs (%1)").arg(iCatalogCounter) );
756 //qDebug() << iCatalogCounter << iCatalogsTotal;
757 iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
760 void AAptInterface::uiUpdaterAptGetInstall()
762 QByteArray data = iProcAptGetInstall->read( iProcAptGetInstall->bytesAvailable() );
763 logToFile( data, false );
764 iProcAptGetInstallOutput.append(data);
769 QStringList lines = QString( data.trimmed() ).split('\n');
772 bool resetprogress = true;
774 QString pkgname = "";
776 for( int i=0; i<lines.count(); i++ )
778 QStringList l = lines.at(i).split(' ');
780 if( l.count()>=4 && l.at(0).startsWith("Get:") ) {
781 oper = "Downloading";
784 Package* pkg = iPackagesAvailable.value(pkgname,0);
786 iAptGetCurrentDownloadFileName = pkg->fileName();
787 iAptGetCurrentFileTotalSize = pkg->size()/1024;
788 pkgname += QString(" (%1 kB)").arg(iAptGetCurrentFileTotalSize);
790 iAptGetDownloadCount++;
791 oper += QString(" %1/%2").arg(iAptGetDownloadCount).arg(iAptGetInstallTotal);
793 if( !iProgressCheckTimer ) {
794 iProgressCheckTimer = new QTimer(this);
795 connect(iProgressCheckTimer,SIGNAL(timeout()),this,SLOT(progressCheckTimerCallback()));
796 iProgressCheckTimer->start(500);
798 resetprogress = false;
799 } else if( l.count()>=2 && l.at(0)=="Unpacking") {
801 if( l.count()>=3 && l.at(1)=="replacement" )
805 iAptGetInstallCount++;
806 oper += QString(" %1/%2").arg(iAptGetInstallCount).arg(iAptGetInstallTotal);
808 } else if( l.count()>=3 && l.at(0)=="Setting" && l.at(1)=="up") {
811 } else if( l.count()>=2 && l.at(0)=="Removing") {
814 iAptGetRemoveCount++;
815 oper += QString(" %1/%2").arg(iAptGetRemoveCount).arg(iAptGetRemoveTotal);
817 } else if( l.count()>=1 && l.at(0)=="Done!") {
818 oper = "Setting up...";
823 /* // this does not seem to work, dpkg always dies first
824 if( lines.at(i).startsWith("***") && lines.at(i).contains("(Y/I/N/O/D/Z)") ) {
825 if( iMainWindow->confirmDialog("Overwrite configuration file?","la la la") )
827 iProcAptGetInstall->write("Y\n");
829 iProcAptGetInstall->write("N\n");
835 if( update && iUiDimmer && iUiDimmer->busy() ) {
836 iUiDimmer->updateText( oper + "<br>" + pkgname );
837 if( resetprogress ) {
838 iUiDimmer->setProgress(-1);
839 if( iProgressCheckTimer ) {
840 iProgressCheckTimer->stop();
841 delete iProgressCheckTimer;
842 iProgressCheckTimer = 0;
848 void AAptInterface::progressCheckTimerCallback()
850 if( iAptGetCurrentDownloadFileName=="" )
853 qint64 prevsize = iAptGetCurrentFileDownloadSize;
854 QFile pkgfile(KAptArchivePartialDir + "/" + iAptGetCurrentDownloadFileName);
855 iAptGetCurrentFileDownloadSize = pkgfile.size()/1024;
857 if( iAptGetCurrentFileDownloadSize >= prevsize ) {
858 iSpeedKbpsPrev = iSpeedKbps;
859 iSpeedKbps = (iAptGetCurrentFileDownloadSize-prevsize)*2;
864 iUpdateSpeed = false;
868 if( iUiDimmer && iUiDimmer->busy() ) {
869 int p = iAptGetCurrentFileDownloadSize*100/iAptGetCurrentFileTotalSize;
870 if( iAptGetDownloadCount > 0 && iAptGetCurrentFileDownloadSize==0 )
872 iUiDimmer->setProgress( p );
873 if( iSpeedKbps>=0 && iSpeedKbpsPrev>=0 && iUpdateSpeed ) {
874 iUiDimmer->setDownloadSpeed( (iSpeedKbps+iSpeedKbpsPrev)/2 );
880 void AAptInterface::communicateStatusToUi(bool success, QString title, QString msg)
882 qDebug() << title << msg;
883 iQueueMessages.append(msg);
885 if( iMainWindow && iOperationsQueue.count()==0 )
887 // title comes from the last finished operation only
888 iMainWindow->operationQueueFinished(iModeLog, success, title, iQueueMessages);
892 QByteArray AAptInterface::readLogFile()
897 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
901 QByteArray line = own.readLine();
908 log = "The log is empty";
913 void AAptInterface::logToFile( QString data, bool logtime )
915 logToFile( data.toAscii(), logtime );
918 void AAptInterface::logToFile( QByteArray data, bool logtime )
922 if( f.open( QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text ) )
926 out << "--- " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << " ---\n";
936 void AAptInterface::readRepositoryInfo()
938 for(int i=0; i<iRepositories.count(); i++) {
939 if( iRepositories.at(i) )
940 delete iRepositories.at(i);
942 iRepositories.clear();
943 bool ownFound = false;
945 QFile own( KOwnRepoFile );
946 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
951 QString line = own.readLine().trimmed();
952 if( line.startsWith("deb ") || line.startsWith("#deb ") )
954 r = new Repository();
955 if( r->setFromString(line) ) {
956 iRepositories.append(r);
957 //qDebug() << r->toListFileNames();
964 if( iRepositories.count() > 0 )
968 QFile names( KOwnRepoNamesFile );
969 if( names.open(QIODevice::ReadOnly | QIODevice::Text ) )
972 while(!names.atEnd() && c<iRepositories.count())
974 QString line = names.readLine().trimmed();
975 if( line.trimmed()!="" )
976 iRepositories.at(c)->setName( line.trimmed() );
986 QFile ham( KHamRepoListFile );
987 if( ham.open(QIODevice::ReadOnly | QIODevice::Text ) )
991 QString line = ham.readLine();
992 Repository* r = new Repository();
993 if( r->setFromString(line) ) {
994 iRepositories.append(r);
1003 bool AAptInterface::writeRepositories()
1005 #ifndef Q_WS_MAEMO_5 // for simulator
1009 iNeedListRefresh = true;
1011 QFile own( KOwnRepoFile );
1012 if( own.open(QIODevice::WriteOnly | QIODevice::Text ) )
1014 QTextStream out(&own);
1015 for( int i=0; i<iRepositories.count(); i++ )
1016 out << iRepositories.at(i)->toString() << "\n";
1020 QFile names( KOwnRepoNamesFile );
1021 if( names.open(QIODevice::WriteOnly | QIODevice::Text ) )
1023 QTextStream out(&names);
1024 for( int i=0; i<iRepositories.count(); i++ )
1025 out << iRepositories.at(i)->name() << "\n";
1029 QFile ham( KAptSourceList );
1030 if( ham.open(QIODevice::WriteOnly | QIODevice::Text ) )
1032 QTextStream out(&ham);
1033 for( int i=0; i<iRepositories.count(); i++ )
1034 out << iRepositories.at(i)->toString() << "\n";
1039 qDebug() << "Failed to write repository list!";
1045 bool AAptInterface::needRepoRefresh()
1047 #ifndef Q_WS_MAEMO_5 // for simulator
1051 if( iNeedRepoRefresh || iSettings->qsettings()->value("need_repo_refresh", false).toBool() ) {
1052 iNeedRepoRefresh = false;
1053 iSettings->qsettings()->setValue("need_repo_refresh", false);
1054 qDebug() << "repo update required, debug 1";
1058 QFile own(KAptSourceList);
1062 qDebug() << "repo update required, debug 2";
1066 QFileInfo a(KLastUpdateFile);
1070 aDate = a.lastModified();
1072 qDebug() << "repo update required, debug 3";
1075 aDate = aDate.addSecs(24*60*60); //24h
1077 if( aDate < QDateTime::currentDateTime() ) {
1078 qDebug() << "repo update required, debug 4";
1082 qDebug() << "repo update not required";
1088 void AAptInterface::startPkgListRead()
1090 logToFile( QString("Start reading package lists") );
1091 qDebug() << "reading package list files";
1093 if( !iNeedListRefresh && !iNeedDpkgRefresh ) {
1094 qDebug() << "no need to refresh package lists";
1095 logToFile( QString("No need to read package lists") );
1096 communicateStatusToUi(true, "Operation finished", "Package data already up to date");
1102 iUiDimmer->updateText("Reading package lists<br>");
1103 iUiDimmer->setProgress(0);
1106 // clear packages lists
1107 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1109 QHashIterator<QString, Package*> a( iPackagesAvailable );
1115 iPackagesAvailable.clear();
1118 if( iNeedDpkgRefresh )
1120 QHashIterator<QString, Package*> i( iPackagesInstalled );
1126 iPackagesInstalled.clear();
1129 // read apt database (available packages)
1131 time_aptread.start();
1133 int pkgcount_apt = 0;
1134 QDir dir( KAptListDir );
1135 QFileInfoList files = dir.entryInfoList();
1137 quint64 totaldatasize = 0;
1138 quint64 currentreaddata = 0;
1139 quint64 lastupdatedata = 0;
1140 quint64 updateinterval = 1000000;
1141 if( iNeedListRefresh && !iSkipRefreshListAndDates ) {
1142 for( int i=0; i<files.count(); i++ )
1144 if( files.at(i).fileName().endsWith("_Packages"))
1145 totaldatasize += files.at(i).size();
1148 if( iNeedDpkgRefresh ) {
1149 QFileInfo dbinfo( KDpkgStatusFile );
1150 totaldatasize += dbinfo.size();
1154 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1158 for( int i=0; i<files.count(); i++ )
1160 Repository* currentRepo = 0;
1161 if( files.at(i).absoluteFilePath().endsWith("_Packages") )
1164 for(int x=0; x<iRepositories.count(); x++) {
1165 if( iRepositories.at(x)->toListFileNames().contains( files.at(i).fileName() ) ) {
1166 currentRepo = iRepositories.at(x);
1170 if( iUiDimmer && currentRepo ) {
1171 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">" + currentRepo->name() + "</font>");
1174 //qDebug() << files.at(i).fileName();
1176 QFile db( files.at(i).absoluteFilePath() );
1177 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1178 qDebug() << "FAIL: Unable to read apt database";
1179 communicateStatusToUi(false, "Error", "Unable to read package lists");
1184 while (!db.atEnd() && !iTerminated) {
1185 Package* newpkg = ReadNextPackage(db, currentreaddata);
1186 //qDebug() << "read" << currentreaddata << "of" << totaldatasize;
1187 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1188 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1189 lastupdatedata = currentreaddata;
1190 QApplication::processEvents();
1193 if( newpkg )//&& !newpkg->name().isEmpty() )
1195 newpkg->addRepository( currentRepo );
1197 Package* exists = iPackagesAvailable.value(newpkg->name(),0);
1199 iPackagesAvailable.insert(newpkg->name(), newpkg);
1201 if( Package::versionCompare(newpkg->version(),exists->version()) )
1203 iPackagesAvailable.remove(exists->name());
1206 iPackagesAvailable.insert(newpkg->name(), newpkg);
1208 if( newpkg->version() == exists->version() ) {
1209 exists->addRepository( currentRepo );
1210 if( newpkg->fullFileNames().count()>0 )
1211 exists->addFullFileName( newpkg->fullFileNames().at(0) );
1213 exists->addFullFileName("unknown_dir/unknown_filename");
1219 }/* else if( newpkg ) {
1228 qDebug() << "apt database read took" << time_aptread.elapsed() << "ms";
1229 qDebug() << "Processed" << filecount << "package list files";
1233 iUiDimmer->setProgress(-1);
1235 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1239 iNeedListRefresh = false;
1240 iNeedDateRefresh = true;
1241 iLastListUpdate = QDateTime::currentDateTime();
1244 // read dpkg database (installed packages)
1245 if( iNeedDpkgRefresh )
1248 QTime time_dpkgread;
1249 time_dpkgread.start();
1251 int pkgcount_dpkg = 0;
1252 QFile db( KDpkgStatusFile );
1253 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1254 qDebug() << "FAIL: Unable to read dpkg database";
1255 communicateStatusToUi(false, "Error", "Unable to read package database");
1261 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">dpkg database</font>");
1264 while (!db.atEnd() && !iTerminated) {
1265 Package* newpkg = ReadNextPackage(db, currentreaddata);
1266 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1267 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1268 lastupdatedata = currentreaddata;
1269 QApplication::processEvents();
1273 if( newpkg->isInstalled() && !newpkg->name().isEmpty() ) {
1274 iPackagesInstalled.insert(newpkg->name(), newpkg);
1283 qDebug() << "dpkg database read took" << time_dpkgread.elapsed() << "ms";
1285 qDebug() << "Processed" << pkgcount_apt << "(apt) and" << pkgcount_dpkg << "(dpkg) package entries";
1286 qDebug() << "In DB:" << iPackagesAvailable.count() << "packages available,"
1287 << iPackagesInstalled.count() << "installed";
1291 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1294 iNeedDpkgRefresh = false;
1295 iLastDpkgUpdate = QDateTime::currentDateTime();
1298 logToFile( QString("Finished reading package lists") );
1300 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">Creating package view</font>");
1301 QApplication::processEvents();
1302 iUiDimmer->setProgress(-1);
1307 communicateStatusToUi(true, "Operation finished", "Package data read");
1312 Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
1314 iMultiLine=MultiLineNone;
1316 Package* pkg = new Package("", this);
1318 bool pkgready = false;
1319 while( !pkgready && !f.atEnd() ) {
1320 QByteArray line = f.readLine();
1321 currentreaddata += line.size();
1322 if( processPackageDataLine(pkg,line) ) {
1327 if( pkg->name() != "" && pkg->isInstalled() ) {
1328 QFileInfo f( KDpkgInfoDir + "/" + pkg->name() + ".list" );
1330 pkg->setDate( f.lastModified() );
1333 pkg->updateStatus();
1335 if( pkg->name() == "" ) {
1342 bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
1344 if( !line.startsWith(' ') && !line.startsWith('\t') )
1345 line = line.trimmed();
1346 if( line.trimmed()=="" )
1349 if( line.startsWith("Package:") )
1351 pkg->setName( line.mid(8).trimmed() );
1352 iMultiLine=MultiLineNone;
1354 else if( line.startsWith("Status:") )
1356 if( line.mid(7).trimmed() == "install ok installed" )
1357 pkg->setInstalled(true);
1359 pkg->setInstalled(false);
1361 else if( line.startsWith("Section:") )
1363 pkg->setSection( line.mid(8).trimmed() );
1365 else if( line.startsWith("Version:") )
1367 pkg->setVersion( line.mid(8).trimmed() );
1369 else if( line.startsWith("Filename:") )
1371 pkg->addFullFileName( line.mid(9).trimmed() );
1373 else if( line.startsWith("Size:") )
1375 pkg->setSize( line.mid(5).trimmed().toInt() );
1377 else if( line.startsWith("Installed-Size:") )
1379 pkg->setInstalledSize( line.mid(15).trimmed().toInt() );
1381 else if( line.startsWith("Maemo-Display-Name:") )
1383 pkg->setMaemoDisplayName( line.mid(19).trimmed() );
1385 else if( line.startsWith("Depends:") )
1387 pkg->appendDepends( line.mid(8).trimmed() );
1389 else if( line.startsWith("Conflicts:") )
1391 pkg->appendConflicts( line.mid(10).trimmed() );
1393 else if( line.startsWith("Pre-Depends:") )
1395 pkg->appendPreDepends( line.mid(12).trimmed() );
1397 else if( line.startsWith("Provides:") )
1399 pkg->appendProvides( line.mid(9).trimmed() );
1401 else if( line.startsWith("Replaces:") )
1403 pkg->appendReplaces( line.mid(9).trimmed() );
1405 else if( line.startsWith("Breaks:") )
1407 pkg->appendBreaks( line.mid(7).trimmed() );
1409 else if( line.startsWith("Recommends:") )
1411 pkg->appendRecommends( line.mid(11).trimmed() );
1413 else if( line.startsWith("Suggests:") )
1415 pkg->appendSuggests( line.mid(9).trimmed() );
1418 if( iMultiLine == MultiLineDesc ) {
1419 if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
1420 if( line.trimmed()!="." )
1421 pkg->appendDescLong( line.trimmed() + "\n" );
1423 pkg->appendDescLong( "\n" );
1425 iMultiLine = MultiLineNone;
1428 else if( iMultiLine == MultiLineIcon ) {
1429 if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
1430 pkg->appendIconData( line.trimmed() );
1432 iMultiLine = MultiLineNone;
1435 else if( iMultiLine == MultiLineUpgradeDesc ) {
1436 if( (line.startsWith(' ') || line.startsWith('\t')) && line.trimmed()!="" ) {
1437 pkg->appendUpgradeDescription( line.trimmed() + "\n" );
1439 iMultiLine = MultiLineNone;
1443 if( line.startsWith("Description:") )
1445 pkg->setDescShort( line.mid(12).trimmed() );
1446 iMultiLine = MultiLineDesc;
1448 else if( line.startsWith("Maemo-Icon-26:") )
1450 if( line.mid(15).trimmed() != "" ) {
1451 pkg->appendIconData( line.mid(15).trimmed() );
1453 iMultiLine = MultiLineIcon;
1455 else if( line.startsWith("Maemo-Upgrade-Description:") )
1457 pkg->appendUpgradeDescription( line.mid(26).trimmed() + "\n" );
1458 iMultiLine = MultiLineUpgradeDesc;
1466 void AAptInterface::writeBlacklist()
1468 QHashIterator<QString, Package*> i( iPackagesAvailable );
1473 if( i.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1474 iBlacklist << i.value()->name();
1476 else if( i.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1477 iBlacklist << (i.value()->name() + " " + i.value()->version());
1481 QHashIterator<QString, Package*> j( iPackagesInstalled );
1486 if( j.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1487 iBlacklist << j.value()->name();
1489 else if( j.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1490 iBlacklist << (j.value()->name() + " " + j.value()->version());
1494 iBlacklist.removeDuplicates();
1496 QFile f( KBlacklistFile );
1497 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1499 QTextStream out(&f);
1500 for( int i=0; i<iBlacklist.count(); i++ )
1501 out << iBlacklist.at(i) << "\n";
1505 qDebug() << "blacklist: wrote" << iBlacklist.count() << "entries";
1508 void AAptInterface::readBlacklist()
1510 QFile f( KBlacklistFile );
1511 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1513 while( !f.atEnd() ) {
1514 QString line = f.readLine().trimmed();
1516 iBlacklist.append(line);
1521 iBlacklist.removeDuplicates();
1523 qDebug() << "blacklist: read" << iBlacklist.count() << "entries";
1525 for( int i=0; i<iBlacklist.count(); i++ )
1527 QStringList parts = iBlacklist.at(i).split(' ');
1528 Package* pkg = iPackagesAvailable.value(parts.at(0).trimmed(), 0);
1529 Package* pkg2 = iPackagesInstalled.value(parts.at(0).trimmed(), 0);
1530 if( parts.count()==1 ) {
1532 pkg->setBlacklisted(BlacklistSelect::BlacklistAll);
1534 pkg2->setBlacklisted(BlacklistSelect::BlacklistAll);
1535 } else if( parts.count()==2 ) {
1536 if( pkg && pkg->version()==parts.at(1) )
1537 pkg->setBlacklisted(BlacklistSelect::BlacklistThis);
1538 if( pkg2 && pkg2->version()==parts.at(1) )
1539 pkg2->setBlacklisted(BlacklistSelect::BlacklistThis);
1541 qDebug() << "Warning: invalid blacklist entry:" << iBlacklist.at(i);
1546 void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList oldstate)
1549 qDebug() << "Warning: trying to remove null package from blacklist";
1553 QStringList newlist;
1554 bool removed = false;
1556 for( int i=0; i<iBlacklist.count(); i++ )
1558 if( oldstate == BlacklistSelect::BlacklistAll )
1560 if( !(iBlacklist.at(i) == pkg->name()) ) {
1561 newlist << iBlacklist.at(i);
1562 } else removed = true;
1563 } else if( oldstate == BlacklistSelect::BlacklistThis ) {
1564 if( !(iBlacklist.at(i) == (pkg->name()+" "+pkg->version())) ) {
1565 newlist << iBlacklist.at(i);
1566 } else removed = true;
1571 qDebug() << "blacklist: removed" << pkg->name();
1573 qDebug() << "blacklist:" << pkg->name() << "not in saved list";
1575 iBlacklist = newlist;
1579 void AAptInterface::startFetchDates()
1581 logToFile( QString("Start fetching package dates") );
1582 qDebug() << "start fetching package dates";
1584 if( !iNeedDateRefresh || iSkipRefreshListAndDates ) {
1585 qDebug() << "no need to fetch dates";
1586 logToFile( QString("No need to fetch dates") );
1587 communicateStatusToUi(true, "Operation finished", "Date information already up to date");
1593 iUiDimmer->updateText("Reading date cache");
1594 iUiDimmer->setProgress(0);
1595 QApplication::processEvents();
1601 iUiDimmer->updateText("Fetching package date information");
1602 QApplication::processEvents();
1605 QNetworkAccessManager* nam = new QNetworkAccessManager(this);
1607 if( iSettings->qsettings()->value("use_proxies").toBool() && iSettings->qsettings()->value("http_proxy").toString()!="" )
1609 QNetworkProxy proxy = Settings::createProxyFromString( iSettings->qsettings()->value("http_proxy").toString() );
1610 nam->setProxy(proxy);
1616 int updProgress = 0;
1618 QHash<QString, Package*> fetchable;
1619 QHashIterator<QString, Package*> i( iPackagesAvailable );
1620 while (i.hasNext() )
1623 if( !i.value()->date().isValid() && i.value()->section().startsWith("user/") && !i.value()->isBlacklisted() )
1625 Repository* repo = 0;
1626 for( int x=0; x<i.value()->repositories().count(); x++ ) {
1627 if( i.value()->repositories().at(x) && i.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1629 repo = i.value()->repositories().at(x);
1634 fetchable.insert(i.value()->name(), i.value());
1639 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(dateFetchNetworkReply(QNetworkReply*)));
1640 iDateRequestsWaiting = 0;
1641 iDateRequestsSent = 0;
1642 iDateRequestsReceived = 0;
1643 iNetworkError = QNetworkReply::NoError;
1645 QString dbgcount = QString("need to fetch date for %1 packages").arg(fetchable.count());
1646 qDebug() << dbgcount;
1647 logToFile(dbgcount);
1649 QHashIterator<QString, Package*> fe( fetchable );
1650 while (fe.hasNext() && !iTerminated)
1654 if( updProgress >=10 ) {
1655 iUiDimmer->setProgress( count*100/fetchable.count() );
1659 if( !fe.value()->date().isValid() && fe.value()->section().startsWith("user/") && !fe.value()->isBlacklisted() )
1662 Repository* repo = 0;
1663 QString fullFilename = "unknown_filename";
1664 for( int x=0; x<fe.value()->repositories().count(); x++ ) {
1665 if( fe.value()->repositories().at(x) && fe.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1667 repo = fe.value()->repositories().at(x);
1668 if( fe.value()->fullFileNames().count()>x )
1669 fullFilename = fe.value()->fullFileNames().at(x);
1676 url = repo->url() + repo->dir() + fullFilename + "#" + fe.value()->name();
1678 //qDebug() << "getting date for" << fe.value()->name();
1682 QNetworkRequest r(u);
1684 if( iDateRequestsReceived == 0 ) {
1685 while( iDateRequestsWaiting>0 ) {
1686 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1689 while( iDateRequestsWaiting>50 ) {
1690 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1694 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1695 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1697 qDebug() << "fatal network error, aborting fetch";
1698 logToFile(QString("Fatal network error, date fetch aborted"));
1702 iDateRequestsSent++;
1703 iDateRequestsWaiting++;
1706 count = iDateRequestsReceived;
1710 while( iDateRequestsWaiting>0 ) {
1711 if( updProgress >=10 ) {
1712 iUiDimmer->setProgress( count*100/fetchable.count() );
1715 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1716 count = iDateRequestsReceived;
1721 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1722 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1724 // don't stop on this error, only inform the user
1725 iMainWindow->notifyDialog("Network error", "There was a network error while fetching date information, the fetch was aborted");
1730 iUiDimmer->setProgress(-1);
1732 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1738 iUiDimmer->setProgress(100);
1739 QApplication::processEvents();
1742 QString dbgstr = QString("sent %1 requests, received %2 replies with %3 errors").arg(iDateRequestsSent).arg(iDateRequestsReceived).arg(iDateRequestErrors);
1747 logToFile( QString("Finished fetching package dates") );
1749 if( fetchable.count()>0 || !dateCacheExists() ) {
1750 iUiDimmer->updateText("Writing date cache");
1751 QApplication::processEvents();
1756 iUiDimmer->updateText("Creating package view");
1757 QApplication::processEvents();
1758 iUiDimmer->setProgress(-1);
1761 communicateStatusToUi(true, "Operation finished", "Package dates fetched");
1762 iNeedDateRefresh = false;
1766 void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
1768 iDateRequestsWaiting--;
1769 iDateRequestsReceived++;
1770 //qDebug() << "reply" << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
1771 iNetworkError = reply->error();
1773 if( reply->error() == QNetworkReply::NoError && reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid() )
1775 QString pkgname = reply->url().fragment();
1776 //qDebug() << pkgname;
1778 if( pkgname.isEmpty() )
1779 qDebug() << "warning: empty packagename in reply";
1781 Package* pkg = iPackagesAvailable.value(pkgname, 0);
1783 pkg->setDate( reply->header(QNetworkRequest::LastModifiedHeader).toDateTime() );
1785 qDebug() << "warning: unknown packagename in reply:" << pkgname;
1789 if( reply->error() != QNetworkReply::NoError ) {
1790 QString dbg = reply->url().fragment() + QString(": error %1: ").arg(reply->error()) + reply->errorString();
1793 iDateRequestErrors++;
1795 reply->deleteLater();
1798 void AAptInterface::writeDateCache()
1800 qDebug() << "writing date cache";
1802 QFile f(KDateCacheFile);
1803 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1805 QTextStream out(&f);
1806 QHashIterator<QString, Package*> i( iPackagesAvailable );
1807 while (i.hasNext() )
1810 if( i.value()->date().isValid() && i.value()->section().startsWith("user/") )
1811 out << i.value()->name() << " " << i.value()->version() << " " << i.value()->date().toString(Qt::ISODate) << "\n";
1815 qDebug() << "Warning: failed to write date cache";
1816 logToFile(QString("Failed to write date cache"));
1820 void AAptInterface::readDateCache()
1822 qDebug() << "reading date cache";
1824 QFile f(KDateCacheFile);
1825 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1827 while( !f.atEnd() ) {
1828 QString line = f.readLine().trimmed();
1829 QStringList parts = line.split(' ');
1830 if( parts.count()==3 ) {
1831 Package* pkg = iPackagesAvailable.value(parts.at(0),0);
1832 if( pkg && pkg->section().startsWith("user/") && pkg->version()==parts.at(1) )
1834 QDateTime dt = QDateTime::fromString( parts.at(2), Qt::ISODate);
1835 if( dt.isValid() ) {
1838 qDebug() << "Warning: Invalid date in date cache";
1839 logToFile(QString("Invalid date in date cache"));
1843 qDebug() << "Warning: error in date cache:" << line;
1844 logToFile(QString("Error in date cache"));
1849 qDebug() << "date cache does not exist";
1853 bool AAptInterface::dateCacheExists()
1855 QFileInfo f(KDateCacheFile);
1859 bool AAptInterface::loadInstallFiles(QStringList files_)