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.";
542 } else if( output.contains("E: Invalid record in the preferences file") ) {
543 msg = "Invalid record in the apt preferences file.";
544 } else if( output.contains("E: Malformed line") && output.contains("in source list") ) {
545 msg = "Malformed line in sources list. Check your repository settings.";
551 void AAptInterface::finishedAptGetUpdate(int exitCode, QProcess::ExitStatus exitStatus)
553 //QByteArray output = iProcAptGetUpdate->readAllStandardOutput();
554 //logToFile( "Output from last process:\n---\n"+output );
558 iProcAptGetUpdate->close();
563 QString title = "Operation finished";
564 QString msg = "Catalogs updated";
565 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
569 msg = finishProcessCommonErrorMessages(iProcAptGetUpdateOutput);
573 iUiDimmer->setProgress(-1);
575 if( iProcAptGetUpdateOutput.contains("Could not resolve ") || iProcAptGetUpdateOutput.contains("W: Failed to fetch") ||
576 iProcAptGetUpdateOutput.contains("Temporary failure resolving") ) {
579 msg = "Failed to update some or all of the catalogs. Check your network connection and/or repository configuration";
583 iNeedRepoRefresh = false;
585 QFile lastupdate(KLastUpdateFile); // create an empty file and/or update the modification time
586 if( lastupdate.open(QIODevice::WriteOnly) )
589 int pos = iProcAptGetUpdateOutput.indexOf("\nFetched ");
591 msg += "<br>apt-get: ";
592 msg += iProcAptGetUpdateOutput.mid(pos+1, iProcAptGetUpdateOutput.indexOf('\n', pos+1)-pos ).trimmed();
599 iProcAptGetUpdate->close();
600 communicateStatusToUi(success, title, msg);
604 void AAptInterface::finishedAptGetSimulate(int exitCode, QProcess::ExitStatus exitStatus)
606 QByteArray output = iProcAptGetSimulate->readAllStandardOutput();
607 logToFile( "Output from last process:\n---\n"+output );
611 iProcAptGetSimulate->close();
616 QString title = "Operation finished";
618 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
622 msg = finishProcessCommonErrorMessages(output);
625 iProcessPackages.clear();
626 iProcessPackageVersions.clear();
629 QList<QByteArray> lines = output.split('\n');
631 for( int i=0; i<lines.count(); i++)
633 QString s = lines.at(i);
634 if( s.startsWith("Inst ") )
636 iProcessPackages << s.section(' ',1,1);
640 int a1 = s.indexOf('[');
641 int a2 = s.indexOf(']');
642 if( a1!=-1 && a2!=-1 && a2>a1) {
643 vs = s.mid(a1+1, a2-a1-1) + " -> ";
645 int b1 = s.indexOf('(');
646 int b2 = s.indexOf(' ',b1);
647 if( b1!=-1 && b2!=-1 && b2>b1) {
648 vs += s.mid(b1+1, b2-b1-1);
651 iProcessPackageVersions << vs;
653 if( s.startsWith("Remv ") )
655 iProcessPackages << s.section(' ',1,1) + "-";
658 int a1 = s.indexOf('[');
659 int a2 = s.indexOf(']');
660 if( a1!=-1 && a2!=-1 && a2>a1) {
661 vs = s.mid(a1+1, a2-a1-1);
664 iProcessPackageVersions << vs;
671 iProcAptGetSimulate->close();
672 communicateStatusToUi(success, title, msg);
676 void AAptInterface::finishedAptGetInstall(int exitCode, QProcess::ExitStatus exitStatus)
678 //QByteArray output = iProcAptGetInstall->readAllStandardOutput();
679 //logToFile( "Output from last process:\n---\n"+output );
682 iProcAptGetInstall->close();
688 QString title = "Operation finished";
689 QString msg = "Package operations finished successfully";
690 if( exitCode != 0 || exitStatus == QProcess::CrashExit || iTerminated )
694 msg = finishProcessCommonErrorMessages(iProcAptGetInstallOutput);
697 if( iProgressCheckTimer ) {
698 iProgressCheckTimer->stop();
699 delete iProgressCheckTimer;
700 iProgressCheckTimer = 0;
703 iUiDimmer->setProgress(-1);
705 iProcessPackages.clear();
706 iProcessPackagesOrig.clear();
707 iProcessPackageVersions.clear();
712 iProcAptGetInstall->close();
713 communicateStatusToUi(success, title, msg);
717 void AAptInterface::finishedAptGetClean(int exitCode, QProcess::ExitStatus exitStatus)
719 QByteArray output = iProcAptGetClean->readAllStandardOutput();
720 // this should produce no output
721 //logToFile( "Output from last process:\n---\n"+output );
725 iProcAptGetClean->close();
730 QString title = "Operation finished";
731 QString msg = "Package cache cleaned";
732 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
736 msg = finishProcessCommonErrorMessages(output);
741 iProcAptGetClean->close();
742 communicateStatusToUi(success, title, msg);
747 void AAptInterface::uiUpdaterAptGetUpdate()
749 QByteArray data = iProcAptGetUpdate->read( iProcAptGetUpdate->bytesAvailable() );
750 logToFile( data, false );
751 iProcAptGetUpdateOutput.append(data);
756 QStringList lines = QString( data.trimmed() ).split('\n');
759 for( int i=0; i<lines.count(); i++ )
761 if( lines.at(i).startsWith("Get:") || lines.at(i).startsWith("Hit ") )
765 infoline = lines.at(i).trimmed();
767 //if( infoline.isEmpty() )
768 //infoline = "arstus";
770 //iUiDimmer->updateText( QString("Updating catalogs (%1)").arg(iCatalogCounter) );
771 //qDebug() << iCatalogCounter << iCatalogsTotal;
773 //iUiDimmer->updateText("Updating catalogs<br><font size=\"-1\">" + infoline + "</font>");
775 if( iCatalogsTotal > 0 )
776 iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
779 void AAptInterface::uiUpdaterAptGetInstall()
781 QByteArray data = iProcAptGetInstall->read( iProcAptGetInstall->bytesAvailable() );
782 logToFile( data, false );
783 iProcAptGetInstallOutput.append(data);
788 QStringList lines = QString( data.trimmed() ).split('\n');
791 bool resetprogress = true;
793 QString pkgname = "";
795 for( int i=0; i<lines.count(); i++ )
797 QStringList l = lines.at(i).split(' ');
799 if( l.count()>=4 && l.at(0).startsWith("Get:") ) {
800 oper = "Downloading";
803 Package* pkg = iPackagesAvailable.value(pkgname,0);
805 iAptGetCurrentDownloadFileName = pkg->fileName();
806 iAptGetCurrentFileTotalSize = pkg->size()/1024;
807 pkgname += QString(" (%1 kB)").arg(iAptGetCurrentFileTotalSize);
809 iAptGetDownloadCount++;
810 oper += QString(" %1/%2").arg(iAptGetDownloadCount).arg(iAptGetInstallTotal);
812 if( !iProgressCheckTimer ) {
813 iProgressCheckTimer = new QTimer(this);
814 connect(iProgressCheckTimer,SIGNAL(timeout()),this,SLOT(progressCheckTimerCallback()));
815 iProgressCheckTimer->start(500);
817 resetprogress = false;
818 } else if( l.count()>=2 && l.at(0)=="Unpacking") {
820 if( l.count()>=3 && l.at(1)=="replacement" )
824 iAptGetInstallCount++;
825 oper += QString(" %1/%2").arg(iAptGetInstallCount).arg(iAptGetInstallTotal);
827 } else if( l.count()>=3 && l.at(0)=="Setting" && l.at(1)=="up") {
830 } else if( l.count()>=2 && l.at(0)=="Removing") {
833 iAptGetRemoveCount++;
834 oper += QString(" %1/%2").arg(iAptGetRemoveCount).arg(iAptGetRemoveTotal);
836 } else if( l.count()>=1 && l.at(0)=="Done!") {
837 oper = "Setting up...";
842 /* // this does not seem to work, dpkg always dies first
843 if( lines.at(i).startsWith("***") && lines.at(i).contains("(Y/I/N/O/D/Z)") ) {
844 if( iMainWindow->confirmDialog("Overwrite configuration file?","la la la") )
846 iProcAptGetInstall->write("Y\n");
848 iProcAptGetInstall->write("N\n");
854 if( update && iUiDimmer && iUiDimmer->busy() ) {
855 iUiDimmer->updateText( oper + "<br>" + pkgname );
856 if( resetprogress ) {
857 iUiDimmer->setProgress(-1);
858 if( iProgressCheckTimer ) {
859 iProgressCheckTimer->stop();
860 delete iProgressCheckTimer;
861 iProgressCheckTimer = 0;
867 void AAptInterface::progressCheckTimerCallback()
869 if( iAptGetCurrentDownloadFileName.isEmpty() )
872 qint64 prevsize = iAptGetCurrentFileDownloadSize;
873 QFile pkgfile(KAptArchivePartialDir + "/" + iAptGetCurrentDownloadFileName);
874 iAptGetCurrentFileDownloadSize = pkgfile.size()/1024;
876 if( iAptGetCurrentFileDownloadSize >= prevsize ) {
877 iSpeedKbpsPrev = iSpeedKbps;
878 iSpeedKbps = (iAptGetCurrentFileDownloadSize-prevsize)*2;
883 iUpdateSpeed = false;
887 if( iUiDimmer && iUiDimmer->busy() ) {
888 int p = iAptGetCurrentFileDownloadSize*100/iAptGetCurrentFileTotalSize;
889 if( iAptGetDownloadCount > 0 && iAptGetCurrentFileDownloadSize==0 )
891 iUiDimmer->setProgress( p );
892 if( iSpeedKbps>=0 && iSpeedKbpsPrev>=0 && iUpdateSpeed ) {
893 iUiDimmer->setDownloadSpeed( (iSpeedKbps+iSpeedKbpsPrev)/2 );
899 void AAptInterface::communicateStatusToUi(bool success, QString title, QString msg)
901 qDebug() << title << msg;
902 iQueueMessages.append(msg);
904 if( iMainWindow && iOperationsQueue.count()==0 )
906 // title comes from the last finished operation only
907 iMainWindow->operationQueueFinished(iModeLog, success, title, iQueueMessages);
911 QByteArray AAptInterface::readLogFile()
916 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
920 QByteArray line = own.readLine();
927 log = "The log is empty";
932 void AAptInterface::logToFile( QString data, bool logtime )
934 logToFile( data.toAscii(), logtime );
937 void AAptInterface::logToFile( QByteArray data, bool logtime )
941 if( f.open( QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text ) )
945 out << "--- " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << " ---\n";
955 void AAptInterface::readRepositoryInfo()
957 for(int i=0; i<iRepositories.count(); i++) {
958 if( iRepositories.at(i) )
959 delete iRepositories.at(i);
961 iRepositories.clear();
962 bool ownFound = false;
964 QFile own( KOwnRepoFile );
965 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
970 QString line = own.readLine().trimmed();
971 if( line.startsWith("deb ") || line.startsWith("#deb ") )
973 r = new Repository();
974 if( r->setFromString(line) ) {
975 iRepositories.append(r);
976 //qDebug() << r->toListFileNames();
983 if( iRepositories.count() > 0 )
987 QFile names( KOwnRepoNamesFile );
988 if( names.open(QIODevice::ReadOnly | QIODevice::Text ) )
991 while(!names.atEnd() && c<iRepositories.count())
993 QString line = names.readLine().trimmed();
994 if( !line.trimmed().isEmpty() )
995 iRepositories.at(c)->setName( line.trimmed() );
1005 QFile ham( KHamRepoListFile );
1006 if( ham.open(QIODevice::ReadOnly | QIODevice::Text ) )
1010 QString line = ham.readLine();
1011 Repository* r = new Repository();
1012 if( r->setFromString(line) ) {
1013 iRepositories.append(r);
1022 bool AAptInterface::writeRepositories()
1024 #ifndef Q_WS_MAEMO_5 // for simulator
1028 iNeedListRefresh = true;
1030 QFile own( KOwnRepoFile );
1031 if( own.open(QIODevice::WriteOnly | QIODevice::Text ) )
1033 QTextStream out(&own);
1034 for( int i=0; i<iRepositories.count(); i++ )
1035 out << iRepositories.at(i)->toString() << "\n";
1039 QFile names( KOwnRepoNamesFile );
1040 if( names.open(QIODevice::WriteOnly | QIODevice::Text ) )
1042 QTextStream out(&names);
1043 for( int i=0; i<iRepositories.count(); i++ )
1044 out << iRepositories.at(i)->name() << "\n";
1048 QFile ham( KAptSourceList );
1049 if( ham.open(QIODevice::WriteOnly | QIODevice::Text ) )
1051 QTextStream out(&ham);
1052 for( int i=0; i<iRepositories.count(); i++ )
1053 out << iRepositories.at(i)->toString() << "\n";
1058 qDebug() << "Failed to write repository list!";
1064 bool AAptInterface::needRepoRefresh()
1066 #ifndef Q_WS_MAEMO_5 // for simulator
1070 if( iNeedRepoRefresh || iSettings->qsettings()->value("need_repo_refresh", false).toBool() ) {
1071 iNeedRepoRefresh = false;
1072 iSettings->qsettings()->setValue("need_repo_refresh", false);
1073 qDebug() << "repo update required, debug 1";
1077 QFile own(KAptSourceList);
1081 qDebug() << "repo update required, debug 2";
1085 QFileInfo a(KLastUpdateFile);
1089 aDate = a.lastModified();
1091 qDebug() << "repo update required, debug 3";
1094 aDate = aDate.addSecs(24*60*60); //24h
1096 if( aDate < QDateTime::currentDateTime() ) {
1097 qDebug() << "repo update required, debug 4";
1101 qDebug() << "repo update not required";
1107 void AAptInterface::startPkgListRead()
1109 logToFile( QString("Start reading package lists") );
1110 qDebug() << "reading package list files";
1112 if( !iNeedListRefresh && !iNeedDpkgRefresh ) {
1113 qDebug() << "no need to refresh package lists";
1114 logToFile( QString("No need to read package lists") );
1115 communicateStatusToUi(true, "Operation finished", "Package data already up to date");
1121 iUiDimmer->updateText("Reading package lists<br>");
1122 iUiDimmer->setProgress(0);
1125 // clear packages lists
1126 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1128 QHashIterator<QString, Package*> a( iPackagesAvailable );
1134 iPackagesAvailable.clear();
1137 if( iNeedDpkgRefresh )
1139 QHashIterator<QString, Package*> i( iPackagesInstalled );
1145 iPackagesInstalled.clear();
1148 // read apt database (available packages)
1150 time_aptread.start();
1152 int pkgcount_apt = 0;
1153 QDir dir( KAptListDir );
1154 QFileInfoList files = dir.entryInfoList();
1156 quint64 totaldatasize = 0;
1157 quint64 currentreaddata = 0;
1158 quint64 lastupdatedata = 0;
1159 quint64 updateinterval = 2000000;
1160 if( iNeedListRefresh && !iSkipRefreshListAndDates ) {
1161 for( int i=0; i<files.count(); i++ )
1163 if( files.at(i).fileName().endsWith("_Packages"))
1164 totaldatasize += files.at(i).size();
1167 if( iNeedDpkgRefresh ) {
1168 QFileInfo dbinfo( KDpkgStatusFile );
1169 totaldatasize += dbinfo.size();
1173 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1177 for( int i=0; i<files.count(); i++ )
1179 Repository* currentRepo = 0;
1180 if( files.at(i).absoluteFilePath().endsWith("_Packages") )
1183 for(int x=0; x<iRepositories.count(); x++) {
1184 if( iRepositories.at(x)->toListFileNames().contains( files.at(i).fileName() ) ) {
1185 currentRepo = iRepositories.at(x);
1189 if( iUiDimmer && currentRepo ) {
1190 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">" + currentRepo->name() + "</font>");
1193 //qDebug() << files.at(i).fileName();
1195 QFile db( files.at(i).absoluteFilePath() );
1196 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1197 qDebug() << "FAIL: Unable to read apt database";
1198 communicateStatusToUi(false, "Error", "Unable to read package lists");
1203 while (!db.atEnd() && !iTerminated) {
1204 Package* newpkg = ReadNextPackage(db, currentreaddata);
1205 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1206 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1207 lastupdatedata = currentreaddata;
1208 QApplication::processEvents();
1213 newpkg->addRepository( currentRepo );
1215 Package* exists = iPackagesAvailable.value(newpkg->name(),0);
1217 iPackagesAvailable.insert(newpkg->name(), newpkg);
1219 if( Package::versionCompare(newpkg->version(),exists->version()) )
1221 iPackagesAvailable.remove(exists->name());
1224 iPackagesAvailable.insert(newpkg->name(), newpkg);
1226 if( newpkg->version() == exists->version() ) {
1227 exists->addRepository( currentRepo );
1228 if( newpkg->fullFileNames().count()>0 )
1229 exists->addFullFileName( newpkg->fullFileNames().at(0) );
1231 exists->addFullFileName("unknown_dir/unknown_filename");
1243 qDebug() << "apt database read took" << time_aptread.elapsed() << "ms";
1244 qDebug() << "Processed" << filecount << "package list files";
1248 iUiDimmer->setProgress(-1);
1250 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1254 iNeedListRefresh = false;
1255 iNeedDateRefresh = true;
1256 iLastListUpdate = QDateTime::currentDateTime();
1259 // read dpkg database (installed packages)
1260 if( iNeedDpkgRefresh )
1263 QTime time_dpkgread;
1264 time_dpkgread.start();
1266 int pkgcount_dpkg = 0;
1267 QFile db( KDpkgStatusFile );
1268 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1269 qDebug() << "FAIL: Unable to read dpkg database";
1270 communicateStatusToUi(false, "Error", "Unable to read package database");
1276 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">dpkg database</font>");
1279 while (!db.atEnd() && !iTerminated) {
1280 Package* newpkg = ReadNextPackage(db, currentreaddata);
1281 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1282 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1283 lastupdatedata = currentreaddata;
1284 QApplication::processEvents();
1288 if( newpkg->isInstalled() && !newpkg->name().isEmpty() ) {
1289 iPackagesInstalled.insert(newpkg->name(), newpkg);
1298 qDebug() << "dpkg database read took" << time_dpkgread.elapsed() << "ms";
1300 qDebug() << "Processed" << pkgcount_apt << "(apt) and" << pkgcount_dpkg << "(dpkg) package entries";
1301 qDebug() << "In DB:" << iPackagesAvailable.count() << "packages available,"
1302 << iPackagesInstalled.count() << "installed";
1306 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1309 iNeedDpkgRefresh = false;
1310 iLastDpkgUpdate = QDateTime::currentDateTime();
1313 logToFile( QString("Finished reading package lists") );
1315 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">Creating package view</font>");
1316 QApplication::processEvents();
1317 iUiDimmer->setProgress(-1);
1321 readPinnedPackages();
1323 communicateStatusToUi(true, "Operation finished", "Package data read");
1328 Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
1330 iMultiLine=MultiLineNone;
1332 Package* pkg = new Package("", this);
1334 bool pkgready = false;
1336 // this is faster than directly reading to QByteArray...
1338 while( !pkgready && !f.atEnd() ) {
1339 f.readLine(iDataReadBuffer,KDataReadBufferSize);
1340 line = iDataReadBuffer;
1341 currentreaddata += line.size();
1342 if( processPackageDataLine(pkg,line) ) {
1347 if( !pkg->name().isEmpty() && pkg->isInstalled() ) {
1348 QFileInfo f( KDpkgInfoDir + "/" + pkg->name() + ".list" );
1350 pkg->setDate( f.lastModified() );
1353 pkg->updateStatus();
1355 if( pkg->name().isEmpty() ) {
1356 qDebug() << "null name package!";
1363 bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
1365 if( line.isEmpty() || line=="\n" )
1370 else if( iMultiLine == MultiLineDesc ) {
1371 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1372 if( line.trimmed()!="." )
1373 pkg->appendDescLong( line.trimmed() + "\n" );
1375 pkg->appendDescLong( "\n" );
1377 iMultiLine = MultiLineNone;
1380 else if( iMultiLine == MultiLineIcon ) {
1381 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1382 pkg->appendIconData( line.trimmed() );
1384 iMultiLine = MultiLineNone;
1387 else if( iMultiLine == MultiLineUpgradeDesc ) {
1388 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1389 pkg->appendUpgradeDescription( line.trimmed() + "\n" );
1391 iMultiLine = MultiLineNone;
1395 else if( line.startsWith("Package:") )
1397 pkg->setName( line.mid(8).trimmed() );
1398 iMultiLine=MultiLineNone;
1400 else if( line.startsWith("Status:") )
1402 if( line.mid(7).trimmed() == "install ok installed" )
1403 pkg->setInstalled(true);
1405 pkg->setInstalled(false);
1407 else if( line.startsWith("Section:") )
1409 pkg->setSection( line.mid(8).trimmed() );
1411 else if( line.startsWith("Version:") )
1413 pkg->setVersion( line.mid(8).trimmed() );
1415 else if( line.startsWith("Filename:") )
1417 pkg->addFullFileName( line.mid(9).trimmed() );
1419 else if( line.startsWith("Size:") )
1421 pkg->setSize( line.mid(5).trimmed().toInt() );
1423 else if( line.startsWith("Installed-Size:") )
1425 pkg->setInstalledSize( line.mid(15).trimmed().toInt() );
1427 else if( line.startsWith("Maemo-Display-Name:") )
1429 pkg->setMaemoDisplayName( line.mid(19).trimmed() );
1431 else if( line.startsWith("Depends:") )
1433 pkg->appendDepends( line.mid(8).trimmed() );
1435 else if( line.startsWith("Conflicts:") )
1437 pkg->appendConflicts( line.mid(10).trimmed() );
1439 else if( line.startsWith("Pre-Depends:") )
1441 pkg->appendPreDepends( line.mid(12).trimmed() );
1443 else if( line.startsWith("Replaces:") )
1445 pkg->appendReplaces( line.mid(9).trimmed() );
1447 else if( line.startsWith("Recommends:") )
1449 pkg->appendRecommends( line.mid(11).trimmed() );
1451 else if( line.startsWith("Suggests:") )
1453 pkg->appendSuggests( line.mid(9).trimmed() );
1455 else if( line.startsWith("Provides:") )
1457 pkg->appendProvides( line.mid(9).trimmed() );
1459 else if( line.startsWith("Breaks:") )
1461 pkg->appendBreaks( line.mid(7).trimmed() );
1463 else if( line.startsWith("Maintainer:") )
1465 pkg->setMaintainer( line.mid(11).trimmed() );
1468 else if( line.startsWith("Description:") )
1470 pkg->setDescShort( line.mid(12).trimmed() );
1471 iMultiLine = MultiLineDesc;
1473 else if( line.startsWith("Maemo-Icon-26:") )
1475 if( line.mid(15).trimmed() != "" ) {
1476 pkg->appendIconData( line.mid(15).trimmed() );
1478 iMultiLine = MultiLineIcon;
1480 else if( line.startsWith("Maemo-Upgrade-Description:") )
1482 pkg->appendUpgradeDescription( line.mid(26).trimmed() + "\n" );
1483 iMultiLine = MultiLineUpgradeDesc;
1491 void AAptInterface::writeBlacklist()
1493 QHashIterator<QString, Package*> i( iPackagesAvailable );
1498 if( i.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1499 iBlacklist << i.value()->name();
1501 else if( i.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1502 iBlacklist << (i.value()->name() + " " + i.value()->version());
1506 QHashIterator<QString, Package*> j( iPackagesInstalled );
1511 if( j.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1512 iBlacklist << j.value()->name();
1514 else if( j.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1515 iBlacklist << (j.value()->name() + " " + j.value()->version());
1519 iBlacklist.removeDuplicates();
1521 QFile f( KBlacklistFile );
1522 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1524 QTextStream out(&f);
1525 for( int i=0; i<iBlacklist.count(); i++ )
1526 out << iBlacklist.at(i) << "\n";
1530 qDebug() << "blacklist: wrote" << iBlacklist.count() << "entries";
1533 void AAptInterface::readBlacklist()
1535 QFile f( KBlacklistFile );
1536 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1538 while( !f.atEnd() ) {
1539 QString line = f.readLine().trimmed();
1541 iBlacklist.append(line);
1546 iBlacklist.removeDuplicates();
1548 qDebug() << "blacklist: read" << iBlacklist.count() << "entries";
1550 for( int i=0; i<iBlacklist.count(); i++ )
1552 QStringList parts = iBlacklist.at(i).split(' ');
1553 Package* pkg = iPackagesAvailable.value(parts.at(0).trimmed(), 0);
1554 Package* pkg2 = iPackagesInstalled.value(parts.at(0).trimmed(), 0);
1555 if( parts.count()==1 ) {
1557 pkg->setBlacklisted(BlacklistSelect::BlacklistAll);
1559 pkg2->setBlacklisted(BlacklistSelect::BlacklistAll);
1560 } else if( parts.count()==2 ) {
1561 if( pkg && pkg->version()==parts.at(1) )
1562 pkg->setBlacklisted(BlacklistSelect::BlacklistThis);
1563 if( pkg2 && pkg2->version()==parts.at(1) )
1564 pkg2->setBlacklisted(BlacklistSelect::BlacklistThis);
1566 qDebug() << "Warning: invalid blacklist entry:" << iBlacklist.at(i);
1571 void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList oldstate)
1574 qDebug() << "Warning: trying to remove null package from blacklist";
1578 QStringList newlist;
1579 bool removed = false;
1581 for( int i=0; i<iBlacklist.count(); i++ )
1583 if( oldstate == BlacklistSelect::BlacklistAll )
1585 if( !(iBlacklist.at(i) == pkg->name()) ) {
1586 newlist << iBlacklist.at(i);
1587 } else removed = true;
1588 } else if( oldstate == BlacklistSelect::BlacklistThis ) {
1589 if( !(iBlacklist.at(i) == (pkg->name()+" "+pkg->version())) ) {
1590 newlist << iBlacklist.at(i);
1591 } else removed = true;
1596 qDebug() << "blacklist: removed" << pkg->name();
1598 qDebug() << "blacklist:" << pkg->name() << "not in saved list";
1600 iBlacklist = newlist;
1604 void AAptInterface::startFetchDates()
1606 logToFile( QString("Start fetching package dates") );
1607 qDebug() << "start fetching package dates";
1609 if( !iNeedDateRefresh || iSkipRefreshListAndDates ) {
1610 qDebug() << "no need to fetch dates";
1611 logToFile( QString("No need to fetch dates") );
1612 communicateStatusToUi(true, "Operation finished", "Date information already up to date");
1618 iUiDimmer->updateText("Reading date cache");
1619 iUiDimmer->setProgress(0);
1620 QApplication::processEvents();
1626 iUiDimmer->updateText("Fetching package date information");
1627 QApplication::processEvents();
1630 QNetworkAccessManager* nam = new QNetworkAccessManager(this);
1632 if( iSettings->qsettings()->value("use_proxies").toBool() && !iSettings->qsettings()->value("http_proxy").toString().isEmpty() )
1634 QNetworkProxy proxy = Settings::createProxyFromString( iSettings->qsettings()->value("http_proxy").toString() );
1635 nam->setProxy(proxy);
1641 int updProgress = 0;
1643 QHash<QString, Package*> fetchable;
1644 QHashIterator<QString, Package*> i( iPackagesAvailable );
1645 while (i.hasNext() )
1648 if( !i.value()->date().isValid() && i.value()->section().startsWith("user/") && !i.value()->isBlacklisted() )
1650 Repository* repo = 0;
1651 for( int x=0; x<i.value()->repositories().count(); x++ ) {
1652 if( i.value()->repositories().at(x) && i.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1654 repo = i.value()->repositories().at(x);
1659 fetchable.insert(i.value()->name(), i.value());
1664 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(dateFetchNetworkReply(QNetworkReply*)));
1665 iDateRequestsWaiting = 0;
1666 iDateRequestsSent = 0;
1667 iDateRequestsReceived = 0;
1668 iNetworkError = QNetworkReply::NoError;
1670 QString dbgcount = QString("need to fetch date for %1 packages").arg(fetchable.count());
1671 qDebug() << dbgcount;
1672 logToFile(dbgcount);
1674 QHashIterator<QString, Package*> fe( fetchable );
1675 while (fe.hasNext() && !iTerminated)
1679 if( updProgress >=20 ) {
1680 iUiDimmer->setProgress( count*100/fetchable.count() );
1684 if( !fe.value()->date().isValid() && fe.value()->section().startsWith("user/") && !fe.value()->isBlacklisted() )
1687 Repository* repo = 0;
1688 QString fullFilename = "unknown_filename";
1689 for( int x=0; x<fe.value()->repositories().count(); x++ ) {
1690 if( fe.value()->repositories().at(x) && fe.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1692 repo = fe.value()->repositories().at(x);
1693 if( fe.value()->fullFileNames().count()>x )
1694 fullFilename = fe.value()->fullFileNames().at(x);
1701 url = repo->url() + repo->dir() + fullFilename + "#" + fe.value()->name();
1703 //qDebug() << "getting date for" << fe.value()->name();
1707 QNetworkRequest r(u);
1709 if( iDateRequestsReceived == 0 ) {
1710 while( iDateRequestsWaiting>0 ) {
1711 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1714 while( iDateRequestsWaiting>50 ) {
1715 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1719 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1720 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1722 qDebug() << "fatal network error, aborting fetch";
1723 logToFile(QString("Fatal network error, date fetch aborted"));
1727 iDateRequestsSent++;
1728 iDateRequestsWaiting++;
1731 count = iDateRequestsReceived;
1735 while( iDateRequestsWaiting>0 ) {
1736 if( updProgress >=20 ) {
1737 iUiDimmer->setProgress( count*100/fetchable.count() );
1740 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1741 count = iDateRequestsReceived;
1746 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1747 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1749 // don't stop on this error, only inform the user
1750 iMainWindow->notifyDialog("Network error", "There was a network error while fetching date information, the fetch was aborted");
1755 iUiDimmer->setProgress(-1);
1757 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1763 iUiDimmer->setProgress(100);
1764 QApplication::processEvents();
1767 QString dbgstr = QString("sent %1 requests, received %2 replies with %3 errors").arg(iDateRequestsSent).arg(iDateRequestsReceived).arg(iDateRequestErrors);
1772 logToFile( QString("Finished fetching package dates") );
1774 if( fetchable.count()>0 || !dateCacheExists() ) {
1775 iUiDimmer->updateText("Writing date cache");
1776 QApplication::processEvents();
1781 iUiDimmer->updateText("Creating package view");
1782 QApplication::processEvents();
1783 iUiDimmer->setProgress(-1);
1786 communicateStatusToUi(true, "Operation finished", "Package dates fetched");
1787 iNeedDateRefresh = false;
1791 void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
1793 iDateRequestsWaiting--;
1794 iDateRequestsReceived++;
1795 //qDebug() << "reply" << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
1796 iNetworkError = reply->error();
1798 if( reply->error() == QNetworkReply::NoError && reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid() )
1800 QString pkgname = reply->url().fragment();
1801 //qDebug() << pkgname;
1803 if( pkgname.isEmpty() )
1804 qDebug() << "warning: empty packagename in reply";
1806 Package* pkg = iPackagesAvailable.value(pkgname, 0);
1808 pkg->setDate( reply->header(QNetworkRequest::LastModifiedHeader).toDateTime() );
1810 qDebug() << "warning: unknown packagename in reply:" << pkgname;
1814 if( reply->error() != QNetworkReply::NoError ) {
1815 QString dbg = reply->url().fragment() + QString(": error %1: ").arg(reply->error()) + reply->errorString();
1818 iDateRequestErrors++;
1820 reply->deleteLater();
1823 void AAptInterface::writeDateCache()
1825 qDebug() << "writing date cache";
1827 QFile f(KDateCacheFile);
1828 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1830 QTextStream out(&f);
1831 QHashIterator<QString, Package*> i( iPackagesAvailable );
1832 while (i.hasNext() )
1835 if( i.value()->date().isValid() && i.value()->section().startsWith("user/") )
1836 out << i.value()->name() << " " << i.value()->version() << " " << i.value()->date().toString(Qt::ISODate) << "\n";
1840 qDebug() << "Warning: failed to write date cache";
1841 logToFile(QString("Failed to write date cache"));
1845 void AAptInterface::readDateCache()
1847 qDebug() << "reading date cache";
1849 QFile f(KDateCacheFile);
1850 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1852 while( !f.atEnd() ) {
1853 QString line = f.readLine().trimmed();
1854 QStringList parts = line.split(' ');
1855 if( parts.count()==3 ) {
1856 Package* pkg = iPackagesAvailable.value(parts.at(0),0);
1857 if( pkg && pkg->section().startsWith("user/") && pkg->version()==parts.at(1) )
1859 QDateTime dt = QDateTime::fromString( parts.at(2), Qt::ISODate);
1860 if( dt.isValid() ) {
1863 qDebug() << "Warning: Invalid date in date cache";
1864 logToFile(QString("Invalid date in date cache"));
1868 qDebug() << "Warning: error in date cache:" << line;
1869 logToFile(QString("Error in date cache"));
1874 qDebug() << "date cache does not exist";
1878 bool AAptInterface::dateCacheExists()
1880 QFileInfo f(KDateCacheFile);
1884 void AAptInterface::readPinnedPackages()
1886 QFile f(KAptPreferencesFile);
1890 bool warnAllPinned = false;
1891 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1893 qDebug() << "apt preferences exist: reading pinned packages";
1894 int pinned_packages = 0;
1897 QString line = f.readLine().trimmed();
1899 if( line=="Package: *" || line=="Package:*")
1900 warnAllPinned = true;
1902 if( line.startsWith("Package:") ) {
1904 QString pkg = line.mid(8).trimmed();
1905 Package* pkg_i = iPackagesInstalled.value(pkg,0);
1907 pkg_i->setPinned(true);
1909 Package* pkg_a = iPackagesAvailable.value(pkg,0);
1911 pkg_a->setPinned(true);
1916 qDebug() << "read" << pinned_packages << "pinned packages";
1919 if( warnAllPinned ) {
1920 iMainWindow->notifyDialog("Warning","You have pinned packages with '*' in apt preferences. It is strongly recommended to "
1921 "remove such settings as they can result in unexpected behavior of Faster Application Manager.");
1925 bool AAptInterface::loadInstallFiles(QStringList files_)