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 iDataReadBuffer = new char[KDataReadBufferSize];
50 iProcAptGetUpdate = new QProcess(this);
51 iProcAptGetSimulate = new QProcess(this);
52 iProcAptGetInstall = new QProcess(this);
53 iProcAptGetClean = new QProcess(this);
55 iProcAptGetUpdate->setProcessChannelMode(QProcess::MergedChannels);
56 iProcAptGetSimulate->setProcessChannelMode(QProcess::MergedChannels);
57 iProcAptGetInstall->setProcessChannelMode(QProcess::MergedChannels);
58 iProcAptGetClean->setProcessChannelMode(QProcess::MergedChannels);
60 connect(iProcAptGetUpdate,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetUpdate(QProcess::ProcessError)));
61 connect(iProcAptGetUpdate,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetUpdate(int,QProcess::ExitStatus)));
62 connect(iProcAptGetUpdate,SIGNAL(readyRead()),this,SLOT(uiUpdaterAptGetUpdate()));
64 connect(iProcAptGetInstall,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetInstall(QProcess::ProcessError)));
65 connect(iProcAptGetInstall,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetInstall(int,QProcess::ExitStatus)));
66 connect(iProcAptGetInstall,SIGNAL(readyRead()),this,SLOT(uiUpdaterAptGetInstall()));
68 connect(iProcAptGetSimulate,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetSimulate(QProcess::ProcessError)));
69 connect(iProcAptGetSimulate,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetSimulate(int,QProcess::ExitStatus)));
71 connect(iProcAptGetClean,SIGNAL(error(QProcess::ProcessError)),this,SLOT(errorAptGetClean(QProcess::ProcessError)));
72 connect(iProcAptGetClean,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(finishedAptGetClean(int,QProcess::ExitStatus)));
74 iProcessPackages.clear();
75 iProcessPackagesOrig.clear();
76 iProcessPackageVersions.clear();
78 QDir logdir(KFapmanDir);
79 logdir.mkpath(KFapmanDir);
81 // create custom apt cache dirs if they don't exist
82 QDir d1(KAptListDir + "/partial");
83 d1.mkpath(KAptListDir + "/partial");
85 // clear log on startup
86 QFile logfile(KLogFile);
89 // clear files left from old versions
90 QFile f1("/root/.fapman/dates.cache");
92 QFile f2("/root/.fapman/lastupdate");
98 AAptInterface::~AAptInterface()
100 if( iProcAptGetUpdate->state() != QProcess::NotRunning )
101 iProcAptGetUpdate->kill();
102 if( iProcAptGetSimulate->state() != QProcess::NotRunning )
103 iProcAptGetSimulate->kill();
104 if( iProcAptGetInstall->state() != QProcess::NotRunning )
105 iProcAptGetInstall->kill();
106 if( iProcAptGetClean->state() != QProcess::NotRunning )
107 iProcAptGetClean->kill();
109 delete iDataReadBuffer;
112 void AAptInterface::addQueuedOperation(interfaceMode mode_)
114 iOperationsQueue.append( mode_ );
117 void AAptInterface::setNeedRefresh(int repos, int lists, int dpkg, int dates)
119 if( repos==0 || repos==1 )
120 iNeedRepoRefresh = (bool)repos;
121 if( lists==0 || lists==1 )
122 iNeedListRefresh = (bool)lists;
123 if( dpkg==0 || dpkg==1 )
124 iNeedDpkgRefresh = (bool)dpkg;
125 if( dates==0 || dates==1 )
126 iNeedDateRefresh = (bool)dates;
129 bool AAptInterface::needListOrDateRefresh()
131 if( iNeedListRefresh || iNeedDpkgRefresh || iNeedDateRefresh )
137 bool AAptInterface::run(dimmer* uiDimmer)
139 if( iMode != ModeNone ) {
140 //qDebug() << "Can't run: not ModeNone";
144 if( iOperationsQueue.count() == 0 ) {
145 qDebug() << "Can't run: Queue empty";
149 iUiDimmer = uiDimmer;
150 iQueueMessages.clear();
158 void AAptInterface::runNext()
160 if( iOperationsQueue.count()==0 ) {
171 iMode = iOperationsQueue.takeAt(0);
172 iModeLog.append(iMode);
174 if( iMode == ModeAptGetUpdate ) {
175 if( !startAptGetUpdate() )
176 errorAptGetUpdate( QProcess::FailedToStart );
178 if( iMode == ModeAptGetInstall ) {
179 if( !startAptGetInstall() )
180 errorAptGetInstall( QProcess::FailedToStart );
182 if( iMode == ModeAptGetSimulate ) {
183 if( !startAptGetSimulate() )
184 errorAptGetSimulate( QProcess::FailedToStart );
186 if( iMode == ModeAptGetClean ) {
187 if( !startAptGetClean() )
188 errorAptGetClean( QProcess::FailedToStart );
190 if( iMode == ModeFetchDates )
193 if( iMode == ModeReadPackages )
197 void AAptInterface::cleanAfterRunEach()
205 void AAptInterface::cleanAfterRunAll()
209 iSkipRefreshListAndDates = false;
212 void AAptInterface::cleanAfterError()
215 iOperationsQueue.clear();
216 iProcessPackages.clear();
217 iProcessPackagesOrig.clear();
218 iProcessPackageVersions.clear();
221 bool AAptInterface::running()
223 if( iMode == ModeNone )
228 bool AAptInterface::cancel()
230 // should return false if can't cancel, or terminate the running process (and clear queue) otherwise
231 if( iMode == ModeNone )
238 if( iMode == ModeAptGetUpdate ) {
239 if( iProcAptGetUpdate->state() == QProcess::Running )
240 iProcAptGetUpdate->terminate();
245 iNeedRepoRefresh = true;
248 if( iMode == ModeAptGetSimulate ) {
249 if( iProcAptGetSimulate->state() == QProcess::Running )
250 iProcAptGetSimulate->terminate();
257 if( iMode == ModeAptGetInstall ) {
258 if( iProcAptGetInstall->state() == QProcess::Running )
259 iProcAptGetInstall->terminate();
266 if( iMode == ModeReadPackages ) {
270 if( iMode == ModeFetchDates ) {
277 bool AAptInterface::startAptGetUpdate()
280 iProcAptGetUpdateOutput.clear();
282 if( !this->writeRepositories() )
284 iNeedListRefresh = true;
285 iNeedDpkgRefresh = true;
286 iNeedDateRefresh = true;
289 iUiDimmer->setProgress(0);
290 iUiDimmer->updateText("Updating catalogs");
295 for( int i=0; i<iRepositories.count(); i++ ) {
296 if( iRepositories.at(i) && iRepositories.at(i)->enabled() ) {
298 QStringList comp = iRepositories.at(i)->components().split(' ');
299 iCatalogsTotal += comp.count();
303 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
304 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
305 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
306 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
308 if( http_proxy != "" )
309 env.insert("http_proxy", http_proxy);
310 if( https_proxy != "" )
311 env.insert("https_proxy", https_proxy);
313 iProcAptGetUpdate->setProcessEnvironment(env);
315 QString runBinary = "/usr/bin/apt-get";
316 QStringList runParameters;
317 runParameters << "-q" << "update"
318 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
319 << "-o" << "Dir::State::lists=" + KAptListDir
320 << "-o" << "Dir::Etc::sourceparts=\"\"";
321 logToFile( runBinary + " " + runParameters.join(" ") );
322 iProcAptGetUpdate->start(runBinary,runParameters);
327 bool AAptInterface::startAptGetSimulate()
329 if( iProcessPackages.count()==0 )
334 iUiDimmer->updateText("Reading dependencies");
337 QString runBinary = "/usr/bin/apt-get";
338 QStringList runParameters;
339 runParameters << "-qsy" << "--allow-unauthenticated"
340 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
341 << "-o" << "Dir::State::lists=" + KAptListDir
342 << "-o" << "Dir::Etc::sourceparts=\"\"";
343 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
344 runParameters << "--auto-remove";
345 runParameters << "install";
346 runParameters << iProcessPackages;
348 logToFile( runBinary + " " + runParameters.join(" ") );
349 iProcAptGetSimulate->start(runBinary,runParameters);
354 bool AAptInterface::startAptGetInstall()
356 if( iProcessPackages.count()==0 )
359 iNeedListRefresh = true;
360 iNeedDpkgRefresh = true;
362 iProcAptGetInstallOutput.clear();
364 qDebug() << "running apt-get install";
366 QString runBinary = "/usr/bin/apt-get";
367 QStringList runParameters;
368 runParameters << "-qy" << "--allow-unauthenticated"
369 << "-o" << "DPkg::options::=--force-confnew"
370 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
371 << "-o" << "Dir::State::lists=" + KAptListDir
372 << "-o" << "Dir::Etc::sourceparts=\"\"";
373 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
374 runParameters << "--auto-remove";
375 runParameters << "install";
376 runParameters << iProcessPackagesOrig;
380 for( int i=0; i<iProcessPackages.count(); i++) {
381 if( iProcessPackages.at(i).endsWith('-') )
387 iAptGetDownloadCount = 0;
388 iAptGetInstallCount = 0;
389 iAptGetRemoveCount = 0;
390 iAptGetInstallTotal = inst_count;
391 iAptGetRemoveTotal = remv_count;
392 iAptGetCurrentFileDownloadSize = 0;
393 iAptGetCurrentFileTotalSize = 0;
394 iAptGetCurrentDownloadFileName = "";
395 iProgressCheckTimer = 0;
398 iUpdateSpeed = false;
400 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
401 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
402 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
403 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
405 if( http_proxy != "" )
406 env.insert("http_proxy", http_proxy);
407 if( https_proxy != "" )
408 env.insert("https_proxy", https_proxy);
410 env.insert("DEBIAN_FRONTEND", "noninteractive");
411 iProcAptGetUpdate->setProcessEnvironment(env);
413 logToFile( runBinary + " " + runParameters.join(" ") );
414 iProcAptGetInstall->start(runBinary,runParameters);
419 bool AAptInterface::startAptGetClean()
421 QString runBinary = "/usr/bin/apt-get";
422 QStringList runParameters;
424 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
425 << "-o" << "Dir::State::lists=" + KAptListDir
426 << "-o" << "Dir::Etc::sourceparts=\"\""
430 iUiDimmer->updateText("Cleaning package cache");
433 logToFile( runBinary + " " + runParameters.join(" ") );
434 iProcAptGetClean->start(runBinary,runParameters);
439 QString AAptInterface::setQProcessErrorMessage(QProcess::ProcessError error)
442 logToFile(QString("Cancelled by user - terminating process"));
443 return "Cancelled by user";
445 else if( error == QProcess::FailedToStart )
446 return "Process failed to start";
447 else if( error == QProcess::Crashed )
448 return "Process crashed";
449 else if( error == QProcess::ReadError )
450 return "QProcess read error";
451 else if( error == QProcess::WriteError )
452 return "QProcess write error";
453 else if( error == QProcess::Timedout )
454 return "QProcess timeout error";
455 else if( error == QProcess::UnknownError )
456 return "QProcess unknown error";
458 return "Unknown error";
461 void AAptInterface::errorAptGetUpdate(QProcess::ProcessError error)
463 QString msg = setQProcessErrorMessage(error);
466 iUiDimmer->setProgress(-1);
468 communicateStatusToUi(false, "Error", msg);
470 iNeedRepoRefresh = true;
474 void AAptInterface::errorAptGetSimulate(QProcess::ProcessError error)
476 QString msg = setQProcessErrorMessage(error);
477 iProcessPackages.clear();
478 iProcessPackagesOrig.clear();
479 iProcessPackageVersions.clear();
481 communicateStatusToUi(false, "Error", msg);
486 void AAptInterface::errorAptGetInstall(QProcess::ProcessError error)
488 QString msg = setQProcessErrorMessage(error);
489 iProcessPackages.clear();
490 iProcessPackagesOrig.clear();
491 iProcessPackageVersions.clear();
493 if( iProgressCheckTimer ) {
494 iProgressCheckTimer->stop();
495 delete iProgressCheckTimer;
496 iProgressCheckTimer = 0;
499 iUiDimmer->setProgress(-1);
502 communicateStatusToUi(false, "Error", msg);
507 void AAptInterface::errorAptGetClean(QProcess::ProcessError error)
509 QString msg = setQProcessErrorMessage(error);
511 communicateStatusToUi(false, "Error", msg);
516 QString AAptInterface::finishProcessCommonErrorMessages(QByteArray& output)
518 QString msg = "Unknown error - see the log for details";
520 if( output.contains("Could not get lock") || output.contains("Could not open lock file") ) {
521 msg = "The package management system is locked by another process or permission was denied";
522 } else if( output.contains("E: Unable to fetch some archives") ) {
523 msg = "Failed to fetch packages - Your network connection might be down or your catalogs could be out of date";
524 } else if( output.contains("E: Couldn't find package") ) {
525 msg = "Missing package, see the log for details - Your catalogs might be out of date";
526 } else if( output.contains("E: Broken packages") ) {
527 msg = "Your system has broken packages or you are trying to install conflicting packages. See the log for details.";
528 } else if( output.contains("E: Handler silently failed") ) {
529 msg = "Handler silently failed - This can happen if you try to install from the forbidden user/hidden category";
530 } else if( iTerminated ) {
531 msg = "The operation was cancelled by user";
532 } else if( output.contains("Temporary failure resolving") || output.contains("Could not resolve host") ) {
533 msg = "DNS errors were reported, check your network connection and/or repository configuration";
534 } else if( output.contains("E: dpkg was interrupted") ) {
535 msg = "Your system has partially installed or broken packages. You'll have to fix this manually. Try dpkg --configure -a";
536 } else if( output.contains("dpkg: error processing") || output.contains("Errors were encountered while processing:") ) {
537 msg = "dpkg reported errors while processing a package - see the log for details";
538 } else if( output.contains("E: Unmet dependencies") ) {
539 msg = "Some of your packages have unmet dependencies which could not be fixed. See the log for details.";
540 } else if( output.contains("E: The method driver") ) {
541 msg = "Apt failed to find a suitable method driver. One or more of your repositories might have an invalid URL.";
547 void AAptInterface::finishedAptGetUpdate(int exitCode, QProcess::ExitStatus exitStatus)
549 //QByteArray output = iProcAptGetUpdate->readAllStandardOutput();
550 //logToFile( "Output from last process:\n---\n"+output );
554 iProcAptGetUpdate->close();
559 QString title = "Operation finished";
560 QString msg = "Catalogs updated";
561 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
565 msg = finishProcessCommonErrorMessages(iProcAptGetUpdateOutput);
569 iUiDimmer->setProgress(-1);
571 if( iProcAptGetUpdateOutput.contains("Could not resolve ") || iProcAptGetUpdateOutput.contains("W: Failed to fetch") ||
572 iProcAptGetUpdateOutput.contains("Temporary failure resolving") ) {
575 msg = "Failed to update some or all of the catalogs. Check your network connection and/or repository configuration";
579 iNeedRepoRefresh = false;
581 QFile lastupdate(KLastUpdateFile); // create an empty file and/or update the modification time
582 if( lastupdate.open(QIODevice::WriteOnly) )
585 int pos = iProcAptGetUpdateOutput.indexOf("\nFetched ");
587 msg += "<br>apt-get: ";
588 msg += iProcAptGetUpdateOutput.mid(pos+1, iProcAptGetUpdateOutput.indexOf('\n', pos+1)-pos ).trimmed();
595 iProcAptGetUpdate->close();
596 communicateStatusToUi(success, title, msg);
600 void AAptInterface::finishedAptGetSimulate(int exitCode, QProcess::ExitStatus exitStatus)
602 QByteArray output = iProcAptGetSimulate->readAllStandardOutput();
603 logToFile( "Output from last process:\n---\n"+output );
607 iProcAptGetSimulate->close();
612 QString title = "Operation finished";
614 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
618 msg = finishProcessCommonErrorMessages(output);
621 iProcessPackages.clear();
622 iProcessPackageVersions.clear();
625 QList<QByteArray> lines = output.split('\n');
627 for( int i=0; i<lines.count(); i++)
629 QString s = lines.at(i);
630 if( s.startsWith("Inst ") )
632 iProcessPackages << s.section(' ',1,1);
636 int a1 = s.indexOf('[');
637 int a2 = s.indexOf(']');
638 if( a1!=-1 && a2!=-1 && a2>a1) {
639 vs = s.mid(a1+1, a2-a1-1) + " -> ";
641 int b1 = s.indexOf('(');
642 int b2 = s.indexOf(' ',b1);
643 if( b1!=-1 && b2!=-1 && b2>b1) {
644 vs += s.mid(b1+1, b2-b1-1);
647 iProcessPackageVersions << vs;
649 if( s.startsWith("Remv ") )
651 iProcessPackages << s.section(' ',1,1) + "-";
654 int a1 = s.indexOf('[');
655 int a2 = s.indexOf(']');
656 if( a1!=-1 && a2!=-1 && a2>a1) {
657 vs = s.mid(a1+1, a2-a1-1);
660 iProcessPackageVersions << vs;
667 iProcAptGetSimulate->close();
668 communicateStatusToUi(success, title, msg);
672 void AAptInterface::finishedAptGetInstall(int exitCode, QProcess::ExitStatus exitStatus)
674 //QByteArray output = iProcAptGetInstall->readAllStandardOutput();
675 //logToFile( "Output from last process:\n---\n"+output );
678 iProcAptGetInstall->close();
684 QString title = "Operation finished";
685 QString msg = "Package operations finished successfully";
686 if( exitCode != 0 || exitStatus == QProcess::CrashExit || iTerminated )
690 msg = finishProcessCommonErrorMessages(iProcAptGetInstallOutput);
693 if( iProgressCheckTimer ) {
694 iProgressCheckTimer->stop();
695 delete iProgressCheckTimer;
696 iProgressCheckTimer = 0;
699 iUiDimmer->setProgress(-1);
701 iProcessPackages.clear();
702 iProcessPackagesOrig.clear();
703 iProcessPackageVersions.clear();
708 iProcAptGetInstall->close();
709 communicateStatusToUi(success, title, msg);
713 void AAptInterface::finishedAptGetClean(int exitCode, QProcess::ExitStatus exitStatus)
715 QByteArray output = iProcAptGetClean->readAllStandardOutput();
716 // this should produce no output
717 //logToFile( "Output from last process:\n---\n"+output );
721 iProcAptGetClean->close();
726 QString title = "Operation finished";
727 QString msg = "Package cache cleaned";
728 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
732 msg = finishProcessCommonErrorMessages(output);
737 iProcAptGetClean->close();
738 communicateStatusToUi(success, title, msg);
743 void AAptInterface::uiUpdaterAptGetUpdate()
745 QByteArray data = iProcAptGetUpdate->read( iProcAptGetUpdate->bytesAvailable() );
746 logToFile( data, false );
747 iProcAptGetUpdateOutput.append(data);
752 QStringList lines = QString( data.trimmed() ).split('\n');
754 for( int i=0; i<lines.count(); i++ )
756 if( lines.at(i).startsWith("Get:") || lines.at(i).startsWith("Hit ") )
759 //iUiDimmer->updateText( QString("Updating catalogs (%1)").arg(iCatalogCounter) );
760 //qDebug() << iCatalogCounter << iCatalogsTotal;
761 iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
764 void AAptInterface::uiUpdaterAptGetInstall()
766 QByteArray data = iProcAptGetInstall->read( iProcAptGetInstall->bytesAvailable() );
767 logToFile( data, false );
768 iProcAptGetInstallOutput.append(data);
773 QStringList lines = QString( data.trimmed() ).split('\n');
776 bool resetprogress = true;
778 QString pkgname = "";
780 for( int i=0; i<lines.count(); i++ )
782 QStringList l = lines.at(i).split(' ');
784 if( l.count()>=4 && l.at(0).startsWith("Get:") ) {
785 oper = "Downloading";
788 Package* pkg = iPackagesAvailable.value(pkgname,0);
790 iAptGetCurrentDownloadFileName = pkg->fileName();
791 iAptGetCurrentFileTotalSize = pkg->size()/1024;
792 pkgname += QString(" (%1 kB)").arg(iAptGetCurrentFileTotalSize);
794 iAptGetDownloadCount++;
795 oper += QString(" %1/%2").arg(iAptGetDownloadCount).arg(iAptGetInstallTotal);
797 if( !iProgressCheckTimer ) {
798 iProgressCheckTimer = new QTimer(this);
799 connect(iProgressCheckTimer,SIGNAL(timeout()),this,SLOT(progressCheckTimerCallback()));
800 iProgressCheckTimer->start(500);
802 resetprogress = false;
803 } else if( l.count()>=2 && l.at(0)=="Unpacking") {
805 if( l.count()>=3 && l.at(1)=="replacement" )
809 iAptGetInstallCount++;
810 oper += QString(" %1/%2").arg(iAptGetInstallCount).arg(iAptGetInstallTotal);
812 } else if( l.count()>=3 && l.at(0)=="Setting" && l.at(1)=="up") {
815 } else if( l.count()>=2 && l.at(0)=="Removing") {
818 iAptGetRemoveCount++;
819 oper += QString(" %1/%2").arg(iAptGetRemoveCount).arg(iAptGetRemoveTotal);
821 } else if( l.count()>=1 && l.at(0)=="Done!") {
822 oper = "Setting up...";
827 /* // this does not seem to work, dpkg always dies first
828 if( lines.at(i).startsWith("***") && lines.at(i).contains("(Y/I/N/O/D/Z)") ) {
829 if( iMainWindow->confirmDialog("Overwrite configuration file?","la la la") )
831 iProcAptGetInstall->write("Y\n");
833 iProcAptGetInstall->write("N\n");
839 if( update && iUiDimmer && iUiDimmer->busy() ) {
840 iUiDimmer->updateText( oper + "<br>" + pkgname );
841 if( resetprogress ) {
842 iUiDimmer->setProgress(-1);
843 if( iProgressCheckTimer ) {
844 iProgressCheckTimer->stop();
845 delete iProgressCheckTimer;
846 iProgressCheckTimer = 0;
852 void AAptInterface::progressCheckTimerCallback()
854 if( iAptGetCurrentDownloadFileName.isEmpty() )
857 qint64 prevsize = iAptGetCurrentFileDownloadSize;
858 QFile pkgfile(KAptArchivePartialDir + "/" + iAptGetCurrentDownloadFileName);
859 iAptGetCurrentFileDownloadSize = pkgfile.size()/1024;
861 if( iAptGetCurrentFileDownloadSize >= prevsize ) {
862 iSpeedKbpsPrev = iSpeedKbps;
863 iSpeedKbps = (iAptGetCurrentFileDownloadSize-prevsize)*2;
868 iUpdateSpeed = false;
872 if( iUiDimmer && iUiDimmer->busy() ) {
873 int p = iAptGetCurrentFileDownloadSize*100/iAptGetCurrentFileTotalSize;
874 if( iAptGetDownloadCount > 0 && iAptGetCurrentFileDownloadSize==0 )
876 iUiDimmer->setProgress( p );
877 if( iSpeedKbps>=0 && iSpeedKbpsPrev>=0 && iUpdateSpeed ) {
878 iUiDimmer->setDownloadSpeed( (iSpeedKbps+iSpeedKbpsPrev)/2 );
884 void AAptInterface::communicateStatusToUi(bool success, QString title, QString msg)
886 qDebug() << title << msg;
887 iQueueMessages.append(msg);
889 if( iMainWindow && iOperationsQueue.count()==0 )
891 // title comes from the last finished operation only
892 iMainWindow->operationQueueFinished(iModeLog, success, title, iQueueMessages);
896 QByteArray AAptInterface::readLogFile()
901 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
905 QByteArray line = own.readLine();
912 log = "The log is empty";
917 void AAptInterface::logToFile( QString data, bool logtime )
919 logToFile( data.toAscii(), logtime );
922 void AAptInterface::logToFile( QByteArray data, bool logtime )
926 if( f.open( QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text ) )
930 out << "--- " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << " ---\n";
940 void AAptInterface::readRepositoryInfo()
942 for(int i=0; i<iRepositories.count(); i++) {
943 if( iRepositories.at(i) )
944 delete iRepositories.at(i);
946 iRepositories.clear();
947 bool ownFound = false;
949 QFile own( KOwnRepoFile );
950 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
955 QString line = own.readLine().trimmed();
956 if( line.startsWith("deb ") || line.startsWith("#deb ") )
958 r = new Repository();
959 if( r->setFromString(line) ) {
960 iRepositories.append(r);
961 //qDebug() << r->toListFileNames();
968 if( iRepositories.count() > 0 )
972 QFile names( KOwnRepoNamesFile );
973 if( names.open(QIODevice::ReadOnly | QIODevice::Text ) )
976 while(!names.atEnd() && c<iRepositories.count())
978 QString line = names.readLine().trimmed();
979 if( !line.trimmed().isEmpty() )
980 iRepositories.at(c)->setName( line.trimmed() );
990 QFile ham( KHamRepoListFile );
991 if( ham.open(QIODevice::ReadOnly | QIODevice::Text ) )
995 QString line = ham.readLine();
996 Repository* r = new Repository();
997 if( r->setFromString(line) ) {
998 iRepositories.append(r);
1007 bool AAptInterface::writeRepositories()
1009 #ifndef Q_WS_MAEMO_5 // for simulator
1013 iNeedListRefresh = true;
1015 QFile own( KOwnRepoFile );
1016 if( own.open(QIODevice::WriteOnly | QIODevice::Text ) )
1018 QTextStream out(&own);
1019 for( int i=0; i<iRepositories.count(); i++ )
1020 out << iRepositories.at(i)->toString() << "\n";
1024 QFile names( KOwnRepoNamesFile );
1025 if( names.open(QIODevice::WriteOnly | QIODevice::Text ) )
1027 QTextStream out(&names);
1028 for( int i=0; i<iRepositories.count(); i++ )
1029 out << iRepositories.at(i)->name() << "\n";
1033 QFile ham( KAptSourceList );
1034 if( ham.open(QIODevice::WriteOnly | QIODevice::Text ) )
1036 QTextStream out(&ham);
1037 for( int i=0; i<iRepositories.count(); i++ )
1038 out << iRepositories.at(i)->toString() << "\n";
1043 qDebug() << "Failed to write repository list!";
1049 bool AAptInterface::needRepoRefresh()
1051 #ifndef Q_WS_MAEMO_5 // for simulator
1055 if( iNeedRepoRefresh || iSettings->qsettings()->value("need_repo_refresh", false).toBool() ) {
1056 iNeedRepoRefresh = false;
1057 iSettings->qsettings()->setValue("need_repo_refresh", false);
1058 qDebug() << "repo update required, debug 1";
1062 QFile own(KAptSourceList);
1066 qDebug() << "repo update required, debug 2";
1070 QFileInfo a(KLastUpdateFile);
1074 aDate = a.lastModified();
1076 qDebug() << "repo update required, debug 3";
1079 aDate = aDate.addSecs(24*60*60); //24h
1081 if( aDate < QDateTime::currentDateTime() ) {
1082 qDebug() << "repo update required, debug 4";
1086 qDebug() << "repo update not required";
1092 void AAptInterface::startPkgListRead()
1094 logToFile( QString("Start reading package lists") );
1095 qDebug() << "reading package list files";
1097 if( !iNeedListRefresh && !iNeedDpkgRefresh ) {
1098 qDebug() << "no need to refresh package lists";
1099 logToFile( QString("No need to read package lists") );
1100 communicateStatusToUi(true, "Operation finished", "Package data already up to date");
1106 iUiDimmer->updateText("Reading package lists<br>");
1107 iUiDimmer->setProgress(0);
1110 // clear packages lists
1111 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1113 QHashIterator<QString, Package*> a( iPackagesAvailable );
1119 iPackagesAvailable.clear();
1122 if( iNeedDpkgRefresh )
1124 QHashIterator<QString, Package*> i( iPackagesInstalled );
1130 iPackagesInstalled.clear();
1133 // read apt database (available packages)
1135 time_aptread.start();
1137 int pkgcount_apt = 0;
1138 QDir dir( KAptListDir );
1139 QFileInfoList files = dir.entryInfoList();
1141 quint64 totaldatasize = 0;
1142 quint64 currentreaddata = 0;
1143 quint64 lastupdatedata = 0;
1144 quint64 updateinterval = 2000000;
1145 if( iNeedListRefresh && !iSkipRefreshListAndDates ) {
1146 for( int i=0; i<files.count(); i++ )
1148 if( files.at(i).fileName().endsWith("_Packages"))
1149 totaldatasize += files.at(i).size();
1152 if( iNeedDpkgRefresh ) {
1153 QFileInfo dbinfo( KDpkgStatusFile );
1154 totaldatasize += dbinfo.size();
1158 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1162 for( int i=0; i<files.count(); i++ )
1164 Repository* currentRepo = 0;
1165 if( files.at(i).absoluteFilePath().endsWith("_Packages") )
1168 for(int x=0; x<iRepositories.count(); x++) {
1169 if( iRepositories.at(x)->toListFileNames().contains( files.at(i).fileName() ) ) {
1170 currentRepo = iRepositories.at(x);
1174 if( iUiDimmer && currentRepo ) {
1175 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">" + currentRepo->name() + "</font>");
1178 //qDebug() << files.at(i).fileName();
1180 QFile db( files.at(i).absoluteFilePath() );
1181 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1182 qDebug() << "FAIL: Unable to read apt database";
1183 communicateStatusToUi(false, "Error", "Unable to read package lists");
1188 while (!db.atEnd() && !iTerminated) {
1189 Package* newpkg = ReadNextPackage(db, currentreaddata);
1190 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1191 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1192 lastupdatedata = currentreaddata;
1193 QApplication::processEvents();
1198 newpkg->addRepository( currentRepo );
1200 Package* exists = iPackagesAvailable.value(newpkg->name(),0);
1202 iPackagesAvailable.insert(newpkg->name(), newpkg);
1204 if( Package::versionCompare(newpkg->version(),exists->version()) )
1206 iPackagesAvailable.remove(exists->name());
1209 iPackagesAvailable.insert(newpkg->name(), newpkg);
1211 if( newpkg->version() == exists->version() ) {
1212 exists->addRepository( currentRepo );
1213 if( newpkg->fullFileNames().count()>0 )
1214 exists->addFullFileName( newpkg->fullFileNames().at(0) );
1216 exists->addFullFileName("unknown_dir/unknown_filename");
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);
1306 readPinnedPackages();
1308 communicateStatusToUi(true, "Operation finished", "Package data read");
1313 Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
1315 iMultiLine=MultiLineNone;
1317 Package* pkg = new Package("", this);
1319 bool pkgready = false;
1321 // this is faster than directly reading to QByteArray...
1323 while( !pkgready && !f.atEnd() ) {
1324 f.readLine(iDataReadBuffer,KDataReadBufferSize);
1325 line = iDataReadBuffer;
1326 currentreaddata += line.size();
1327 if( processPackageDataLine(pkg,line) ) {
1332 if( !pkg->name().isEmpty() && pkg->isInstalled() ) {
1333 QFileInfo f( KDpkgInfoDir + "/" + pkg->name() + ".list" );
1335 pkg->setDate( f.lastModified() );
1338 pkg->updateStatus();
1340 if( pkg->name().isEmpty() ) {
1341 qDebug() << "null name package!";
1348 bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
1350 if( line.isEmpty() || line=="\n" )
1355 else if( iMultiLine == MultiLineDesc ) {
1356 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1357 if( line.trimmed()!="." )
1358 pkg->appendDescLong( line.trimmed() + "\n" );
1360 pkg->appendDescLong( "\n" );
1362 iMultiLine = MultiLineNone;
1365 else if( iMultiLine == MultiLineIcon ) {
1366 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1367 pkg->appendIconData( line.trimmed() );
1369 iMultiLine = MultiLineNone;
1372 else if( iMultiLine == MultiLineUpgradeDesc ) {
1373 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1374 pkg->appendUpgradeDescription( line.trimmed() + "\n" );
1376 iMultiLine = MultiLineNone;
1380 else if( line.startsWith("Package:") )
1382 pkg->setName( line.mid(8).trimmed() );
1383 iMultiLine=MultiLineNone;
1385 else if( line.startsWith("Status:") )
1387 if( line.mid(7).trimmed() == "install ok installed" )
1388 pkg->setInstalled(true);
1390 pkg->setInstalled(false);
1392 else if( line.startsWith("Section:") )
1394 pkg->setSection( line.mid(8).trimmed() );
1396 else if( line.startsWith("Version:") )
1398 pkg->setVersion( line.mid(8).trimmed() );
1400 else if( line.startsWith("Filename:") )
1402 pkg->addFullFileName( line.mid(9).trimmed() );
1404 else if( line.startsWith("Size:") )
1406 pkg->setSize( line.mid(5).trimmed().toInt() );
1408 else if( line.startsWith("Installed-Size:") )
1410 pkg->setInstalledSize( line.mid(15).trimmed().toInt() );
1412 else if( line.startsWith("Maemo-Display-Name:") )
1414 pkg->setMaemoDisplayName( line.mid(19).trimmed() );
1416 else if( line.startsWith("Depends:") )
1418 pkg->appendDepends( line.mid(8).trimmed() );
1420 else if( line.startsWith("Conflicts:") )
1422 pkg->appendConflicts( line.mid(10).trimmed() );
1424 else if( line.startsWith("Pre-Depends:") )
1426 pkg->appendPreDepends( line.mid(12).trimmed() );
1428 else if( line.startsWith("Replaces:") )
1430 pkg->appendReplaces( line.mid(9).trimmed() );
1432 else if( line.startsWith("Recommends:") )
1434 pkg->appendRecommends( line.mid(11).trimmed() );
1436 else if( line.startsWith("Suggests:") )
1438 pkg->appendSuggests( line.mid(9).trimmed() );
1440 else if( line.startsWith("Provides:") )
1442 pkg->appendProvides( line.mid(9).trimmed() );
1444 else if( line.startsWith("Breaks:") )
1446 pkg->appendBreaks( line.mid(7).trimmed() );
1449 else if( line.startsWith("Description:") )
1451 pkg->setDescShort( line.mid(12).trimmed() );
1452 iMultiLine = MultiLineDesc;
1454 else if( line.startsWith("Maemo-Icon-26:") )
1456 if( line.mid(15).trimmed() != "" ) {
1457 pkg->appendIconData( line.mid(15).trimmed() );
1459 iMultiLine = MultiLineIcon;
1461 else if( line.startsWith("Maemo-Upgrade-Description:") )
1463 pkg->appendUpgradeDescription( line.mid(26).trimmed() + "\n" );
1464 iMultiLine = MultiLineUpgradeDesc;
1472 void AAptInterface::writeBlacklist()
1474 QHashIterator<QString, Package*> i( iPackagesAvailable );
1479 if( i.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1480 iBlacklist << i.value()->name();
1482 else if( i.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1483 iBlacklist << (i.value()->name() + " " + i.value()->version());
1487 QHashIterator<QString, Package*> j( iPackagesInstalled );
1492 if( j.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1493 iBlacklist << j.value()->name();
1495 else if( j.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1496 iBlacklist << (j.value()->name() + " " + j.value()->version());
1500 iBlacklist.removeDuplicates();
1502 QFile f( KBlacklistFile );
1503 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1505 QTextStream out(&f);
1506 for( int i=0; i<iBlacklist.count(); i++ )
1507 out << iBlacklist.at(i) << "\n";
1511 qDebug() << "blacklist: wrote" << iBlacklist.count() << "entries";
1514 void AAptInterface::readBlacklist()
1516 QFile f( KBlacklistFile );
1517 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1519 while( !f.atEnd() ) {
1520 QString line = f.readLine().trimmed();
1522 iBlacklist.append(line);
1527 iBlacklist.removeDuplicates();
1529 qDebug() << "blacklist: read" << iBlacklist.count() << "entries";
1531 for( int i=0; i<iBlacklist.count(); i++ )
1533 QStringList parts = iBlacklist.at(i).split(' ');
1534 Package* pkg = iPackagesAvailable.value(parts.at(0).trimmed(), 0);
1535 Package* pkg2 = iPackagesInstalled.value(parts.at(0).trimmed(), 0);
1536 if( parts.count()==1 ) {
1538 pkg->setBlacklisted(BlacklistSelect::BlacklistAll);
1540 pkg2->setBlacklisted(BlacklistSelect::BlacklistAll);
1541 } else if( parts.count()==2 ) {
1542 if( pkg && pkg->version()==parts.at(1) )
1543 pkg->setBlacklisted(BlacklistSelect::BlacklistThis);
1544 if( pkg2 && pkg2->version()==parts.at(1) )
1545 pkg2->setBlacklisted(BlacklistSelect::BlacklistThis);
1547 qDebug() << "Warning: invalid blacklist entry:" << iBlacklist.at(i);
1552 void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList oldstate)
1555 qDebug() << "Warning: trying to remove null package from blacklist";
1559 QStringList newlist;
1560 bool removed = false;
1562 for( int i=0; i<iBlacklist.count(); i++ )
1564 if( oldstate == BlacklistSelect::BlacklistAll )
1566 if( !(iBlacklist.at(i) == pkg->name()) ) {
1567 newlist << iBlacklist.at(i);
1568 } else removed = true;
1569 } else if( oldstate == BlacklistSelect::BlacklistThis ) {
1570 if( !(iBlacklist.at(i) == (pkg->name()+" "+pkg->version())) ) {
1571 newlist << iBlacklist.at(i);
1572 } else removed = true;
1577 qDebug() << "blacklist: removed" << pkg->name();
1579 qDebug() << "blacklist:" << pkg->name() << "not in saved list";
1581 iBlacklist = newlist;
1585 void AAptInterface::startFetchDates()
1587 logToFile( QString("Start fetching package dates") );
1588 qDebug() << "start fetching package dates";
1590 if( !iNeedDateRefresh || iSkipRefreshListAndDates ) {
1591 qDebug() << "no need to fetch dates";
1592 logToFile( QString("No need to fetch dates") );
1593 communicateStatusToUi(true, "Operation finished", "Date information already up to date");
1599 iUiDimmer->updateText("Reading date cache");
1600 iUiDimmer->setProgress(0);
1601 QApplication::processEvents();
1607 iUiDimmer->updateText("Fetching package date information");
1608 QApplication::processEvents();
1611 QNetworkAccessManager* nam = new QNetworkAccessManager(this);
1613 if( iSettings->qsettings()->value("use_proxies").toBool() && !iSettings->qsettings()->value("http_proxy").toString().isEmpty() )
1615 QNetworkProxy proxy = Settings::createProxyFromString( iSettings->qsettings()->value("http_proxy").toString() );
1616 nam->setProxy(proxy);
1622 int updProgress = 0;
1624 QHash<QString, Package*> fetchable;
1625 QHashIterator<QString, Package*> i( iPackagesAvailable );
1626 while (i.hasNext() )
1629 if( !i.value()->date().isValid() && i.value()->section().startsWith("user/") && !i.value()->isBlacklisted() )
1631 Repository* repo = 0;
1632 for( int x=0; x<i.value()->repositories().count(); x++ ) {
1633 if( i.value()->repositories().at(x) && i.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1635 repo = i.value()->repositories().at(x);
1640 fetchable.insert(i.value()->name(), i.value());
1645 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(dateFetchNetworkReply(QNetworkReply*)));
1646 iDateRequestsWaiting = 0;
1647 iDateRequestsSent = 0;
1648 iDateRequestsReceived = 0;
1649 iNetworkError = QNetworkReply::NoError;
1651 QString dbgcount = QString("need to fetch date for %1 packages").arg(fetchable.count());
1652 qDebug() << dbgcount;
1653 logToFile(dbgcount);
1655 QHashIterator<QString, Package*> fe( fetchable );
1656 while (fe.hasNext() && !iTerminated)
1660 if( updProgress >=20 ) {
1661 iUiDimmer->setProgress( count*100/fetchable.count() );
1665 if( !fe.value()->date().isValid() && fe.value()->section().startsWith("user/") && !fe.value()->isBlacklisted() )
1668 Repository* repo = 0;
1669 QString fullFilename = "unknown_filename";
1670 for( int x=0; x<fe.value()->repositories().count(); x++ ) {
1671 if( fe.value()->repositories().at(x) && fe.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1673 repo = fe.value()->repositories().at(x);
1674 if( fe.value()->fullFileNames().count()>x )
1675 fullFilename = fe.value()->fullFileNames().at(x);
1682 url = repo->url() + repo->dir() + fullFilename + "#" + fe.value()->name();
1684 //qDebug() << "getting date for" << fe.value()->name();
1688 QNetworkRequest r(u);
1690 if( iDateRequestsReceived == 0 ) {
1691 while( iDateRequestsWaiting>0 ) {
1692 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1695 while( iDateRequestsWaiting>50 ) {
1696 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1700 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1701 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1703 qDebug() << "fatal network error, aborting fetch";
1704 logToFile(QString("Fatal network error, date fetch aborted"));
1708 iDateRequestsSent++;
1709 iDateRequestsWaiting++;
1712 count = iDateRequestsReceived;
1716 while( iDateRequestsWaiting>0 ) {
1717 if( updProgress >=20 ) {
1718 iUiDimmer->setProgress( count*100/fetchable.count() );
1721 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1722 count = iDateRequestsReceived;
1727 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1728 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1730 // don't stop on this error, only inform the user
1731 iMainWindow->notifyDialog("Network error", "There was a network error while fetching date information, the fetch was aborted");
1736 iUiDimmer->setProgress(-1);
1738 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1744 iUiDimmer->setProgress(100);
1745 QApplication::processEvents();
1748 QString dbgstr = QString("sent %1 requests, received %2 replies with %3 errors").arg(iDateRequestsSent).arg(iDateRequestsReceived).arg(iDateRequestErrors);
1753 logToFile( QString("Finished fetching package dates") );
1755 if( fetchable.count()>0 || !dateCacheExists() ) {
1756 iUiDimmer->updateText("Writing date cache");
1757 QApplication::processEvents();
1762 iUiDimmer->updateText("Creating package view");
1763 QApplication::processEvents();
1764 iUiDimmer->setProgress(-1);
1767 communicateStatusToUi(true, "Operation finished", "Package dates fetched");
1768 iNeedDateRefresh = false;
1772 void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
1774 iDateRequestsWaiting--;
1775 iDateRequestsReceived++;
1776 //qDebug() << "reply" << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
1777 iNetworkError = reply->error();
1779 if( reply->error() == QNetworkReply::NoError && reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid() )
1781 QString pkgname = reply->url().fragment();
1782 //qDebug() << pkgname;
1784 if( pkgname.isEmpty() )
1785 qDebug() << "warning: empty packagename in reply";
1787 Package* pkg = iPackagesAvailable.value(pkgname, 0);
1789 pkg->setDate( reply->header(QNetworkRequest::LastModifiedHeader).toDateTime() );
1791 qDebug() << "warning: unknown packagename in reply:" << pkgname;
1795 if( reply->error() != QNetworkReply::NoError ) {
1796 QString dbg = reply->url().fragment() + QString(": error %1: ").arg(reply->error()) + reply->errorString();
1799 iDateRequestErrors++;
1801 reply->deleteLater();
1804 void AAptInterface::writeDateCache()
1806 qDebug() << "writing date cache";
1808 QFile f(KDateCacheFile);
1809 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1811 QTextStream out(&f);
1812 QHashIterator<QString, Package*> i( iPackagesAvailable );
1813 while (i.hasNext() )
1816 if( i.value()->date().isValid() && i.value()->section().startsWith("user/") )
1817 out << i.value()->name() << " " << i.value()->version() << " " << i.value()->date().toString(Qt::ISODate) << "\n";
1821 qDebug() << "Warning: failed to write date cache";
1822 logToFile(QString("Failed to write date cache"));
1826 void AAptInterface::readDateCache()
1828 qDebug() << "reading date cache";
1830 QFile f(KDateCacheFile);
1831 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1833 while( !f.atEnd() ) {
1834 QString line = f.readLine().trimmed();
1835 QStringList parts = line.split(' ');
1836 if( parts.count()==3 ) {
1837 Package* pkg = iPackagesAvailable.value(parts.at(0),0);
1838 if( pkg && pkg->section().startsWith("user/") && pkg->version()==parts.at(1) )
1840 QDateTime dt = QDateTime::fromString( parts.at(2), Qt::ISODate);
1841 if( dt.isValid() ) {
1844 qDebug() << "Warning: Invalid date in date cache";
1845 logToFile(QString("Invalid date in date cache"));
1849 qDebug() << "Warning: error in date cache:" << line;
1850 logToFile(QString("Error in date cache"));
1855 qDebug() << "date cache does not exist";
1859 bool AAptInterface::dateCacheExists()
1861 QFileInfo f(KDateCacheFile);
1865 void AAptInterface::readPinnedPackages()
1867 QFile f(KAptPreferencesFile);
1871 bool warnAllPinned = false;
1872 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1874 qDebug() << "apt preferences exist: reading pinned packages";
1875 int pinned_packages = 0;
1878 QString line = f.readLine().trimmed();
1880 if( line=="Package: *" || line=="Package:*")
1881 warnAllPinned = true;
1883 if( line.startsWith("Package:") ) {
1885 QString pkg = line.mid(8).trimmed();
1886 Package* pkg_i = iPackagesInstalled.value(pkg,0);
1888 pkg_i->setPinned(true);
1890 Package* pkg_a = iPackagesAvailable.value(pkg,0);
1892 pkg_a->setPinned(true);
1897 qDebug() << "read" << pinned_packages << "pinned packages";
1900 if( warnAllPinned ) {
1901 iMainWindow->notifyDialog("Warning","You have pinned packages with '*' in apt preferences. It is strongly recommended to "
1902 "remove such settings as they can result in unexpected behavior of Faster Application Manager.");
1906 bool AAptInterface::loadInstallFiles(QStringList files_)