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 // qprocesses are automatically deleted by their parent
111 QHashIterator<QString, Package*> a( iPackagesAvailable );
117 iPackagesAvailable.clear();
119 QHashIterator<QString, Package*> i( iPackagesInstalled );
125 iPackagesInstalled.clear();
127 for(int x=0; x<iRepositories.count(); x++) {
128 if( iRepositories.at(x) )
129 delete iRepositories.at(x);
131 iRepositories.clear();
133 delete[] iDataReadBuffer;
137 void AAptInterface::addQueuedOperation(interfaceMode mode_)
139 iOperationsQueue.append( mode_ );
142 void AAptInterface::setNeedRefresh(int repos, int lists, int dpkg, int dates)
144 if( repos==0 || repos==1 )
145 iNeedRepoRefresh = (bool)repos;
146 if( lists==0 || lists==1 )
147 iNeedListRefresh = (bool)lists;
148 if( dpkg==0 || dpkg==1 )
149 iNeedDpkgRefresh = (bool)dpkg;
150 if( dates==0 || dates==1 )
151 iNeedDateRefresh = (bool)dates;
154 bool AAptInterface::needListOrDateRefresh()
156 if( iNeedListRefresh || iNeedDpkgRefresh || iNeedDateRefresh )
162 bool AAptInterface::run(dimmer* uiDimmer)
164 if( iMode != ModeNone ) {
165 //qDebug() << "Can't run: not ModeNone";
169 if( iOperationsQueue.count() == 0 ) {
170 qDebug() << "Can't run: Queue empty";
174 iUiDimmer = uiDimmer;
175 iQueueMessages.clear();
183 void AAptInterface::runNext()
185 if( iOperationsQueue.count()==0 ) {
196 iMode = iOperationsQueue.takeAt(0);
197 iModeLog.append(iMode);
199 if( iMode == ModeAptGetUpdate ) {
200 if( !startAptGetUpdate() )
201 errorAptGetUpdate( QProcess::FailedToStart );
203 if( iMode == ModeAptGetInstall ) {
204 if( !startAptGetInstall() )
205 errorAptGetInstall( QProcess::FailedToStart );
207 if( iMode == ModeAptGetSimulate ) {
208 if( !startAptGetSimulate() )
209 errorAptGetSimulate( QProcess::FailedToStart );
211 if( iMode == ModeAptGetClean ) {
212 if( !startAptGetClean() )
213 errorAptGetClean( QProcess::FailedToStart );
215 if( iMode == ModeFetchDates )
218 if( iMode == ModeReadPackages )
222 void AAptInterface::cleanAfterRunEach()
230 void AAptInterface::cleanAfterRunAll()
234 iSkipRefreshListAndDates = false;
237 void AAptInterface::cleanAfterError()
240 iOperationsQueue.clear();
241 iProcessPackages.clear();
242 iProcessPackagesOrig.clear();
243 iProcessPackageVersions.clear();
246 bool AAptInterface::running() const
248 if( iMode == ModeNone )
253 bool AAptInterface::cancel()
255 // should return false if can't cancel, or terminate the running process (and clear queue) otherwise
256 if( iMode == ModeNone )
263 if( iMode == ModeAptGetUpdate ) {
264 if( iProcAptGetUpdate->state() == QProcess::Running )
265 iProcAptGetUpdate->terminate();
270 iNeedRepoRefresh = true;
273 if( iMode == ModeAptGetSimulate ) {
274 if( iProcAptGetSimulate->state() == QProcess::Running )
275 iProcAptGetSimulate->terminate();
282 if( iMode == ModeAptGetInstall ) {
283 if( iProcAptGetInstall->state() == QProcess::Running )
284 iProcAptGetInstall->terminate();
291 if( iMode == ModeReadPackages ) {
295 if( iMode == ModeFetchDates ) {
302 bool AAptInterface::startAptGetUpdate()
305 iProcAptGetUpdateOutput.clear();
307 if( !this->writeRepositories() )
309 iNeedListRefresh = true;
310 iNeedDpkgRefresh = true;
311 iNeedDateRefresh = true;
314 iUiDimmer->setProgress(0);
315 iUiDimmer->updateText("Updating catalogs");
320 for( int i=0; i<iRepositories.count(); i++ ) {
321 if( iRepositories.at(i) && iRepositories.at(i)->enabled() ) {
323 QStringList comp = iRepositories.at(i)->components().split(' ');
324 iCatalogsTotal += comp.count();
328 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
329 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
330 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
331 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
333 if( http_proxy != "" )
334 env.insert("http_proxy", http_proxy);
335 if( https_proxy != "" )
336 env.insert("https_proxy", https_proxy);
338 iProcAptGetUpdate->setProcessEnvironment(env);
340 QString runBinary = "/usr/bin/apt-get";
341 QStringList runParameters;
342 runParameters << "-q" << "update"
343 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
344 << "-o" << "Dir::State::lists=" + KAptListDir
345 << "-o" << "Dir::Etc::sourceparts=\"\"";
346 logToFile( runBinary + " " + runParameters.join(" ") );
347 iProcAptGetUpdate->start(runBinary,runParameters);
352 bool AAptInterface::startAptGetSimulate()
354 if( iProcessPackages.count()==0 )
359 iUiDimmer->updateText("Reading dependencies");
362 QString runBinary = "/usr/bin/apt-get";
363 QStringList runParameters;
364 runParameters << "-qsy" << "--allow-unauthenticated"
365 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
366 << "-o" << "Dir::State::lists=" + KAptListDir
367 << "-o" << "Dir::Etc::sourceparts=\"\"";
368 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
369 runParameters << "--auto-remove";
370 runParameters << "install";
371 runParameters << iProcessPackages;
373 logToFile( runBinary + " " + runParameters.join(" ") );
374 iProcAptGetSimulate->start(runBinary,runParameters);
379 bool AAptInterface::startAptGetInstall()
381 if( iProcessPackages.count()==0 )
384 iNeedListRefresh = true;
385 iNeedDpkgRefresh = true;
387 iProcAptGetInstallOutput.clear();
389 qDebug() << "running apt-get install";
391 QString runBinary = "/usr/bin/apt-get";
392 QStringList runParameters;
393 runParameters << "-qy" << "--allow-unauthenticated"
394 << "-o" << "DPkg::options::=--force-confnew"
395 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
396 << "-o" << "Dir::State::lists=" + KAptListDir
397 << "-o" << "Dir::Etc::sourceparts=\"\"";
398 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
399 runParameters << "--auto-remove";
400 runParameters << "install";
401 runParameters << iProcessPackagesOrig;
405 for( int i=0; i<iProcessPackages.count(); i++) {
406 if( iProcessPackages.at(i).endsWith('-') )
412 iAptGetDownloadCount = 0;
413 iAptGetInstallCount = 0;
414 iAptGetRemoveCount = 0;
415 iAptGetInstallTotal = inst_count;
416 iAptGetRemoveTotal = remv_count;
417 iAptGetCurrentFileDownloadSize = 0;
418 iAptGetCurrentFileTotalSize = 0;
419 iAptGetCurrentDownloadFileName = "";
420 iProgressCheckTimer = 0;
423 iUpdateSpeed = false;
425 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
426 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
427 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
428 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
430 if( http_proxy != "" )
431 env.insert("http_proxy", http_proxy);
432 if( https_proxy != "" )
433 env.insert("https_proxy", https_proxy);
435 env.insert("DEBIAN_FRONTEND", "noninteractive");
436 iProcAptGetUpdate->setProcessEnvironment(env);
438 logToFile( runBinary + " " + runParameters.join(" ") );
439 iProcAptGetInstall->start(runBinary,runParameters);
444 bool AAptInterface::startAptGetClean()
446 QString runBinary = "/usr/bin/apt-get";
447 QStringList runParameters;
449 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
450 << "-o" << "Dir::State::lists=" + KAptListDir
451 << "-o" << "Dir::Etc::sourceparts=\"\""
455 iUiDimmer->updateText("Cleaning package cache");
458 logToFile( runBinary + " " + runParameters.join(" ") );
459 iProcAptGetClean->start(runBinary,runParameters);
464 QString AAptInterface::setQProcessErrorMessage(QProcess::ProcessError error)
467 logToFile(QString("Cancelled by user - terminating process"));
468 return "Cancelled by user";
470 else if( error == QProcess::FailedToStart )
471 return "Process failed to start";
472 else if( error == QProcess::Crashed )
473 return "Process crashed";
474 else if( error == QProcess::ReadError )
475 return "QProcess read error";
476 else if( error == QProcess::WriteError )
477 return "QProcess write error";
478 else if( error == QProcess::Timedout )
479 return "QProcess timeout error";
480 else if( error == QProcess::UnknownError )
481 return "QProcess unknown error";
483 return "Unknown error";
486 void AAptInterface::errorAptGetUpdate(QProcess::ProcessError error)
488 QString msg = setQProcessErrorMessage(error);
491 iUiDimmer->setProgress(-1);
493 communicateStatusToUi(false, "Error", msg);
495 iNeedRepoRefresh = true;
499 void AAptInterface::errorAptGetSimulate(QProcess::ProcessError error)
501 QString msg = setQProcessErrorMessage(error);
502 iProcessPackages.clear();
503 iProcessPackagesOrig.clear();
504 iProcessPackageVersions.clear();
506 communicateStatusToUi(false, "Error", msg);
511 void AAptInterface::errorAptGetInstall(QProcess::ProcessError error)
513 QString msg = setQProcessErrorMessage(error);
514 iProcessPackages.clear();
515 iProcessPackagesOrig.clear();
516 iProcessPackageVersions.clear();
518 if( iProgressCheckTimer ) {
519 iProgressCheckTimer->stop();
520 delete iProgressCheckTimer;
521 iProgressCheckTimer = 0;
524 iUiDimmer->setProgress(-1);
527 communicateStatusToUi(false, "Error", msg);
532 void AAptInterface::errorAptGetClean(QProcess::ProcessError error)
534 QString msg = setQProcessErrorMessage(error);
536 communicateStatusToUi(false, "Error", msg);
541 QString AAptInterface::finishProcessCommonErrorMessages(QByteArray& output)
543 QString msg = "Unknown error - see the log for details";
545 if( output.contains("Could not get lock") || output.contains("Could not open lock file") ) {
546 msg = "The package management system is locked by another process or permission was denied";
547 } else if( output.contains("E: Unable to fetch some archives") ) {
548 msg = "Failed to fetch packages - Your network connection might be down or your catalogs could be out of date";
549 } else if( output.contains("E: Couldn't find package") ) {
550 msg = "Missing package, see the log for details - Your catalogs might be out of date";
551 } else if( output.contains("E: Broken packages") ) {
552 msg = "Your system has broken packages or you are trying to install conflicting packages. See the log for details.";
553 } else if( output.contains("E: Handler silently failed") ) {
554 msg = "Handler silently failed - This can happen if you try to install from the forbidden user/hidden category. Disabling OVI store repositories might help.";
555 } else if( iTerminated ) {
556 msg = "The operation was cancelled by user";
557 } else if( output.contains("Temporary failure resolving") || output.contains("Could not resolve host") ) {
558 msg = "DNS errors were reported, check your network connection and/or repository configuration";
559 } else if( output.contains("E: dpkg was interrupted") ) {
560 msg = "Your system has partially installed or broken packages. You'll have to fix this manually. Try dpkg --configure -a";
561 } else if( output.contains("dpkg: error processing") || output.contains("Errors were encountered while processing:") ) {
562 msg = "dpkg reported errors while processing a package - see the log for details";
563 } else if( output.contains("E: Unmet dependencies") ) {
564 msg = "Some of your packages have unmet dependencies which could not be fixed. See the log for details.";
565 } else if( output.contains("E: The method driver") ) {
566 msg = "Apt failed to find a suitable method driver. One or more of your repositories might have an invalid URL.";
567 } else if( output.contains("E: Invalid record in the preferences file") ) {
568 msg = "Invalid record in the apt preferences file.";
569 } else if( output.contains("E: Malformed line") && output.contains("in source list") ) {
570 msg = "Malformed line in sources list. Check your repository settings.";
576 void AAptInterface::finishedAptGetUpdate(int exitCode, QProcess::ExitStatus exitStatus)
578 //QByteArray output = iProcAptGetUpdate->readAllStandardOutput();
579 //logToFile( "Output from last process:\n---\n"+output );
583 iProcAptGetUpdate->close();
588 QString title = "Operation finished";
589 QString msg = "Catalogs updated";
590 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
594 msg = finishProcessCommonErrorMessages(iProcAptGetUpdateOutput);
598 iUiDimmer->setProgress(-1);
600 if( iProcAptGetUpdateOutput.contains("Could not resolve ") || iProcAptGetUpdateOutput.contains("W: Failed to fetch") ||
601 iProcAptGetUpdateOutput.contains("Temporary failure resolving") ) {
604 msg = "Failed to update some or all of the catalogs. Check your network connection and/or repository configuration";
608 iNeedRepoRefresh = false;
610 QFile lastupdate(KLastUpdateFile); // create an empty file and/or update the modification time
611 if( lastupdate.open(QIODevice::WriteOnly) )
614 int pos = iProcAptGetUpdateOutput.indexOf("\nFetched ");
616 msg += "<br>apt-get: ";
617 msg += iProcAptGetUpdateOutput.mid(pos+1, iProcAptGetUpdateOutput.indexOf('\n', pos+1)-pos ).trimmed();
624 iProcAptGetUpdate->close();
625 communicateStatusToUi(success, title, msg);
629 void AAptInterface::finishedAptGetSimulate(int exitCode, QProcess::ExitStatus exitStatus)
631 QByteArray output = iProcAptGetSimulate->readAllStandardOutput();
632 logToFile( "Output from last process:\n---\n"+output );
636 iProcAptGetSimulate->close();
641 QString title = "Operation finished";
643 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
647 msg = finishProcessCommonErrorMessages(output);
650 iProcessPackages.clear();
651 iProcessPackageVersions.clear();
654 QList<QByteArray> lines = output.split('\n');
656 for( int i=0; i<lines.count(); i++)
658 QString s = lines.at(i);
659 if( s.startsWith("Inst ") )
661 iProcessPackages << s.section(' ',1,1);
665 int a1 = s.indexOf('[');
666 int a2 = s.indexOf(']');
667 if( a1!=-1 && a2!=-1 && a2>a1) {
668 vs = s.mid(a1+1, a2-a1-1) + " -> ";
670 int b1 = s.indexOf('(');
671 int b2 = s.indexOf(' ',b1);
672 if( b1!=-1 && b2!=-1 && b2>b1) {
673 vs += s.mid(b1+1, b2-b1-1);
676 iProcessPackageVersions << vs;
678 if( s.startsWith("Remv ") )
680 iProcessPackages << s.section(' ',1,1) + "-";
683 int a1 = s.indexOf('[');
684 int a2 = s.indexOf(']');
685 if( a1!=-1 && a2!=-1 && a2>a1) {
686 vs = s.mid(a1+1, a2-a1-1);
689 iProcessPackageVersions << vs;
696 iProcAptGetSimulate->close();
697 communicateStatusToUi(success, title, msg);
701 void AAptInterface::finishedAptGetInstall(int exitCode, QProcess::ExitStatus exitStatus)
703 //QByteArray output = iProcAptGetInstall->readAllStandardOutput();
704 //logToFile( "Output from last process:\n---\n"+output );
707 iProcAptGetInstall->close();
713 QString title = "Operation finished";
714 QString msg = "Package operations finished successfully";
715 if( exitCode != 0 || exitStatus == QProcess::CrashExit || iTerminated )
719 msg = finishProcessCommonErrorMessages(iProcAptGetInstallOutput);
722 if( iProgressCheckTimer ) {
723 iProgressCheckTimer->stop();
724 delete iProgressCheckTimer;
725 iProgressCheckTimer = 0;
728 iUiDimmer->setProgress(-1);
730 iProcessPackages.clear();
731 iProcessPackagesOrig.clear();
732 iProcessPackageVersions.clear();
737 iProcAptGetInstall->close();
738 communicateStatusToUi(success, title, msg);
742 void AAptInterface::finishedAptGetClean(int exitCode, QProcess::ExitStatus exitStatus)
744 QByteArray output = iProcAptGetClean->readAllStandardOutput();
745 // this should produce no output
746 //logToFile( "Output from last process:\n---\n"+output );
750 iProcAptGetClean->close();
755 QString title = "Operation finished";
756 QString msg = "Package cache cleaned";
757 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
761 msg = finishProcessCommonErrorMessages(output);
766 iProcAptGetClean->close();
767 communicateStatusToUi(success, title, msg);
772 void AAptInterface::uiUpdaterAptGetUpdate()
774 QByteArray data = iProcAptGetUpdate->read( iProcAptGetUpdate->bytesAvailable() );
775 logToFile( data, false );
776 iProcAptGetUpdateOutput.append(data);
781 QStringList lines = QString( data.trimmed() ).split('\n');
784 for( int i=0; i<lines.count(); i++ )
786 if( lines.at(i).startsWith("Get:") || lines.at(i).startsWith("Hit ") )
790 infoline = lines.at(i).trimmed();
792 //if( infoline.isEmpty() )
793 //infoline = "arstus";
795 //iUiDimmer->updateText( QString("Updating catalogs (%1)").arg(iCatalogCounter) );
796 //qDebug() << iCatalogCounter << iCatalogsTotal;
798 //iUiDimmer->updateText("Updating catalogs<br><font size=\"-1\">" + infoline + "</font>");
800 if( iCatalogsTotal > 0 )
801 iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
804 void AAptInterface::uiUpdaterAptGetInstall()
806 QByteArray data = iProcAptGetInstall->read( iProcAptGetInstall->bytesAvailable() );
807 logToFile( data, false );
808 iProcAptGetInstallOutput.append(data);
813 QStringList lines = QString( data.trimmed() ).split('\n');
816 bool resetprogress = true;
818 QString pkgname = "";
820 for( int i=0; i<lines.count(); i++ )
822 QStringList l = lines.at(i).split(' ');
824 if( l.count()>=4 && l.at(0).startsWith("Get:") ) {
825 oper = "Downloading";
828 Package* pkg = iPackagesAvailable.value(pkgname,0);
830 iAptGetCurrentDownloadFileName = pkg->fileName();
831 iAptGetCurrentFileTotalSize = pkg->size()/1024;
832 pkgname += QString(" (%L1 kB)").arg(iAptGetCurrentFileTotalSize);
834 iAptGetDownloadCount++;
835 oper += QString(" %1/%2").arg(iAptGetDownloadCount).arg(iAptGetInstallTotal);
837 if( !iProgressCheckTimer ) {
838 iProgressCheckTimer = new QTimer(this);
839 connect(iProgressCheckTimer,SIGNAL(timeout()),this,SLOT(progressCheckTimerCallback()));
840 iProgressCheckTimer->start(500);
842 resetprogress = false;
843 } else if( l.count()>=2 && l.at(0)=="Unpacking") {
845 if( l.count()>=3 && l.at(1)=="replacement" )
849 iAptGetInstallCount++;
850 oper += QString(" %1/%2").arg(iAptGetInstallCount).arg(iAptGetInstallTotal);
852 } else if( l.count()>=3 && l.at(0)=="Setting" && l.at(1)=="up") {
855 } else if( l.count()>=2 && l.at(0)=="Removing") {
858 iAptGetRemoveCount++;
859 oper += QString(" %1/%2").arg(iAptGetRemoveCount).arg(iAptGetRemoveTotal);
861 } else if( l.count()>=1 && l.at(0)=="Done!") {
862 oper = "Setting up...";
867 /* // this does not seem to work, dpkg always dies first
868 if( lines.at(i).startsWith("***") && lines.at(i).contains("(Y/I/N/O/D/Z)") ) {
869 if( iMainWindow->confirmDialog("Overwrite configuration file?","la la la") )
871 iProcAptGetInstall->write("Y\n");
873 iProcAptGetInstall->write("N\n");
879 if( update && iUiDimmer && iUiDimmer->busy() ) {
880 iUiDimmer->updateText( oper + "<br>" + pkgname );
881 if( resetprogress ) {
882 iUiDimmer->setProgress(-1);
883 if( iProgressCheckTimer ) {
884 iProgressCheckTimer->stop();
885 delete iProgressCheckTimer;
886 iProgressCheckTimer = 0;
892 void AAptInterface::progressCheckTimerCallback()
894 if( iAptGetCurrentDownloadFileName.isEmpty() )
897 qint64 prevsize = iAptGetCurrentFileDownloadSize;
898 QFile pkgfile(KAptArchivePartialDir + "/" + iAptGetCurrentDownloadFileName);
899 iAptGetCurrentFileDownloadSize = pkgfile.size()/1024;
901 if( iAptGetCurrentFileDownloadSize >= prevsize ) {
902 iSpeedKbpsPrev = iSpeedKbps;
903 iSpeedKbps = (iAptGetCurrentFileDownloadSize-prevsize)*2;
908 iUpdateSpeed = false;
912 if( iUiDimmer && iUiDimmer->busy() ) {
913 int p = iAptGetCurrentFileDownloadSize*100/iAptGetCurrentFileTotalSize;
914 if( iAptGetDownloadCount > 0 && iAptGetCurrentFileDownloadSize==0 )
916 iUiDimmer->setProgress( p );
917 if( iSpeedKbps>=0 && iSpeedKbpsPrev>=0 && iUpdateSpeed ) {
918 iUiDimmer->setDownloadSpeed( (iSpeedKbps+iSpeedKbpsPrev)/2 );
924 void AAptInterface::communicateStatusToUi(bool success, QString title, QString msg)
926 qDebug() << title << msg;
927 iQueueMessages.append(msg);
929 if( iMainWindow && iOperationsQueue.count()==0 )
931 // title comes from the last finished operation only
932 iMainWindow->operationQueueFinished(iModeLog, success, title, iQueueMessages);
936 QByteArray AAptInterface::readLogFile()
941 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
945 QByteArray line = own.readLine();
952 log = "The log is empty";
957 void AAptInterface::logToFile( QString data, bool logtime )
959 logToFile( data.toAscii(), logtime );
962 void AAptInterface::logToFile( QByteArray data, bool logtime )
966 if( f.open( QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text ) )
970 out << "--- " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << " ---\n";
980 void AAptInterface::readRepositoryInfo()
982 for(int i=0; i<iRepositories.count(); i++) {
983 if( iRepositories.at(i) )
984 delete iRepositories.at(i);
986 iRepositories.clear();
987 bool ownFound = false;
989 QFile own( KOwnRepoFile );
990 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
995 QString line = own.readLine().trimmed();
996 if( line.startsWith("deb ") || line.startsWith("#deb ") )
998 r = new Repository();
999 if( r->setFromString(line) ) {
1000 iRepositories.append(r);
1001 //qDebug() << r->toListFileNames();
1009 if( iRepositories.count() > 0 )
1013 QFile names( KOwnRepoNamesFile );
1014 if( names.open(QIODevice::ReadOnly | QIODevice::Text ) )
1017 while(!names.atEnd() && c<iRepositories.count())
1019 QString line = names.readLine().trimmed();
1020 if( !line.trimmed().isEmpty() )
1021 iRepositories.at(c)->setName( line.trimmed() );
1031 QFile ham( KHamRepoListFile );
1032 if( ham.open(QIODevice::ReadOnly | QIODevice::Text ) )
1036 QString line = ham.readLine();
1037 Repository* r = new Repository();
1038 if( r->setFromString(line) ) {
1039 iRepositories.append(r);
1049 bool AAptInterface::writeRepositories()
1051 #ifndef Q_WS_MAEMO_5 // for simulator
1055 iNeedListRefresh = true;
1057 QFile own( KOwnRepoFile );
1058 if( own.open(QIODevice::WriteOnly | QIODevice::Text ) )
1060 QTextStream out(&own);
1061 for( int i=0; i<iRepositories.count(); i++ )
1062 out << iRepositories.at(i)->toString() << "\n";
1066 QFile names( KOwnRepoNamesFile );
1067 if( names.open(QIODevice::WriteOnly | QIODevice::Text ) )
1069 QTextStream out(&names);
1070 for( int i=0; i<iRepositories.count(); i++ )
1071 out << iRepositories.at(i)->name() << "\n";
1075 QFile ham( KAptSourceList );
1076 if( ham.open(QIODevice::WriteOnly | QIODevice::Text ) )
1078 QTextStream out(&ham);
1079 for( int i=0; i<iRepositories.count(); i++ )
1080 out << iRepositories.at(i)->toString() << "\n";
1085 qDebug() << "Failed to write repository list!";
1091 bool AAptInterface::needRepoRefresh()
1093 #ifndef Q_WS_MAEMO_5 // for simulator
1097 if( iNeedRepoRefresh || iSettings->qsettings()->value("need_repo_refresh", false).toBool() ) {
1098 iNeedRepoRefresh = false;
1099 iSettings->qsettings()->setValue("need_repo_refresh", false);
1100 qDebug() << "repo update required, debug 1";
1104 QFile own(KAptSourceList);
1108 qDebug() << "repo update required, debug 2";
1112 QFileInfo a(KLastUpdateFile);
1116 aDate = a.lastModified();
1118 qDebug() << "repo update required, debug 3";
1121 aDate = aDate.addSecs(24*60*60); //24h
1123 if( aDate < QDateTime::currentDateTime() ) {
1124 qDebug() << "repo update required, debug 4";
1128 qDebug() << "repo update not required";
1134 void AAptInterface::startPkgListRead()
1136 logToFile( QString("Start reading package lists") );
1137 qDebug() << "reading package list files";
1139 if( !iNeedListRefresh && !iNeedDpkgRefresh ) {
1140 qDebug() << "no need to refresh package lists";
1141 logToFile( QString("No need to read package lists") );
1142 communicateStatusToUi(true, "Operation finished", "Package data already up to date");
1148 iUiDimmer->updateText("Reading package lists<br>");
1149 iUiDimmer->setProgress(0);
1152 // clear packages lists
1153 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1155 QHashIterator<QString, Package*> a( iPackagesAvailable );
1161 iPackagesAvailable.clear();
1164 if( iNeedDpkgRefresh )
1166 QHashIterator<QString, Package*> i( iPackagesInstalled );
1172 iPackagesInstalled.clear();
1175 // read apt database (available packages)
1177 time_aptread.start();
1179 int pkgcount_apt = 0;
1180 QDir dir( KAptListDir );
1181 QFileInfoList files = dir.entryInfoList();
1183 quint64 totaldatasize = 0;
1184 quint64 currentreaddata = 0;
1185 quint64 lastupdatedata = 0;
1186 quint64 updateinterval = 2000000;
1187 if( iNeedListRefresh && !iSkipRefreshListAndDates ) {
1188 for( int i=0; i<files.count(); i++ )
1190 if( files.at(i).fileName().endsWith("_Packages"))
1191 totaldatasize += files.at(i).size();
1194 if( iNeedDpkgRefresh ) {
1195 QFileInfo dbinfo( KDpkgStatusFile );
1196 totaldatasize += dbinfo.size();
1200 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1204 for( int i=0; i<files.count(); i++ )
1206 Repository* currentRepo = 0;
1207 if( files.at(i).absoluteFilePath().endsWith("_Packages") )
1210 for(int x=0; x<iRepositories.count(); x++) {
1211 if( iRepositories.at(x)->toListFileNames().contains( files.at(i).fileName() ) ) {
1212 currentRepo = iRepositories.at(x);
1216 if( iUiDimmer && currentRepo ) {
1217 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">" + currentRepo->name() + "</font>");
1220 //qDebug() << files.at(i).fileName();
1222 QFile db( files.at(i).absoluteFilePath() );
1223 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1224 qDebug() << "FAIL: Unable to read apt database";
1225 communicateStatusToUi(false, "Error", "Unable to read package lists");
1230 while (!db.atEnd() && !iTerminated) {
1231 Package* newpkg = ReadNextPackage(db, currentreaddata);
1232 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1233 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1234 lastupdatedata = currentreaddata;
1235 QApplication::processEvents();
1240 newpkg->addRepository( currentRepo );
1242 Package* exists = iPackagesAvailable.value(newpkg->name(),0);
1244 iPackagesAvailable.insert(newpkg->name(), newpkg);
1246 if( Package::versionCompare(newpkg->version(),exists->version()) )
1248 iPackagesAvailable.remove(exists->name());
1251 iPackagesAvailable.insert(newpkg->name(), newpkg);
1253 if( newpkg->version() == exists->version() ) {
1254 exists->addRepository( currentRepo );
1255 if( newpkg->fullFileNames().count()>0 )
1256 exists->addFullFileName( newpkg->fullFileNames().at(0) );
1258 exists->addFullFileName("unknown_dir/unknown_filename");
1270 qDebug() << "apt database read took" << time_aptread.elapsed() << "ms";
1271 qDebug() << "Processed" << filecount << "package list files";
1275 iUiDimmer->setProgress(-1);
1277 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1281 iNeedListRefresh = false;
1282 iNeedDateRefresh = true;
1283 iLastListUpdate = QDateTime::currentDateTime();
1286 // read dpkg database (installed packages)
1287 if( iNeedDpkgRefresh )
1290 QTime time_dpkgread;
1291 time_dpkgread.start();
1293 int pkgcount_dpkg = 0;
1294 QFile db( KDpkgStatusFile );
1295 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1296 qDebug() << "FAIL: Unable to read dpkg database";
1297 communicateStatusToUi(false, "Error", "Unable to read package database");
1303 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">dpkg database</font>");
1306 while (!db.atEnd() && !iTerminated) {
1307 Package* newpkg = ReadNextPackage(db, currentreaddata);
1308 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1309 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1310 lastupdatedata = currentreaddata;
1311 QApplication::processEvents();
1315 if( newpkg->isInstalled() && !newpkg->name().isEmpty() ) {
1316 iPackagesInstalled.insert(newpkg->name(), newpkg);
1325 qDebug() << "dpkg database read took" << time_dpkgread.elapsed() << "ms";
1327 qDebug() << "Processed" << pkgcount_apt << "(apt) and" << pkgcount_dpkg << "(dpkg) package entries";
1328 qDebug() << "In DB:" << iPackagesAvailable.count() << "packages available,"
1329 << iPackagesInstalled.count() << "installed";
1333 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1336 iNeedDpkgRefresh = false;
1337 iLastDpkgUpdate = QDateTime::currentDateTime();
1340 logToFile( QString("Finished reading package lists") );
1342 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">Creating package view</font>");
1343 QApplication::processEvents();
1344 iUiDimmer->setProgress(-1);
1348 readPinnedPackages();
1350 communicateStatusToUi(true, "Operation finished", "Package data read");
1355 Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
1357 iMultiLine=MultiLineNone;
1359 Package* pkg = new Package("", this);
1361 bool pkgready = false;
1363 // this is faster than directly reading to QByteArray...
1365 while( !pkgready && !f.atEnd() ) {
1366 f.readLine(iDataReadBuffer,KDataReadBufferSize);
1367 line = iDataReadBuffer;
1368 currentreaddata += line.size();
1369 if( processPackageDataLine(pkg,line) ) {
1374 if( !pkg->name().isEmpty() && pkg->isInstalled() ) {
1375 QFileInfo f( KDpkgInfoDir + "/" + pkg->name() + ".list" );
1377 pkg->setDate( f.lastModified() );
1380 pkg->updateStatus();
1382 if( pkg->name().isEmpty() ) {
1383 qDebug() << "null name package!";
1390 bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
1392 if( line.isEmpty() || line=="\n" )
1397 else if( iMultiLine == MultiLineDesc ) {
1398 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1399 if( line.trimmed()!="." )
1400 pkg->appendDescLong( line.trimmed() + "\n" );
1402 pkg->appendDescLong( "\n" );
1404 iMultiLine = MultiLineNone;
1407 else if( iMultiLine == MultiLineIcon ) {
1408 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1409 pkg->appendIconData( line.trimmed() );
1411 iMultiLine = MultiLineNone;
1414 else if( iMultiLine == MultiLineUpgradeDesc ) {
1415 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1416 pkg->appendUpgradeDescription( line.trimmed() + "\n" );
1418 iMultiLine = MultiLineNone;
1422 else if( line.startsWith("Package:") )
1424 pkg->setName( line.mid(8).trimmed() );
1425 iMultiLine=MultiLineNone;
1427 else if( line.startsWith("Status:") )
1429 if( line.mid(7).trimmed() == "install ok installed" )
1430 pkg->setInstalled(true);
1432 pkg->setInstalled(false);
1434 else if( line.startsWith("Section:") )
1436 pkg->setSection( line.mid(8).trimmed() );
1438 else if( line.startsWith("Version:") )
1440 pkg->setVersion( line.mid(8).trimmed() );
1442 else if( line.startsWith("Filename:") )
1444 pkg->addFullFileName( line.mid(9).trimmed() );
1446 else if( line.startsWith("Size:") )
1448 pkg->setSize( line.mid(5).trimmed().toInt() );
1450 else if( line.startsWith("Installed-Size:") )
1452 pkg->setInstalledSize( line.mid(15).trimmed().toInt() );
1454 else if( line.startsWith("Maemo-Display-Name:") )
1456 pkg->setMaemoDisplayName( line.mid(19).trimmed() );
1458 else if( line.startsWith("Depends:") )
1460 pkg->appendDepends( line.mid(8).trimmed() );
1462 else if( line.startsWith("Conflicts:") )
1464 pkg->appendConflicts( line.mid(10).trimmed() );
1466 else if( line.startsWith("Pre-Depends:") )
1468 pkg->appendPreDepends( line.mid(12).trimmed() );
1470 else if( line.startsWith("Replaces:") )
1472 pkg->appendReplaces( line.mid(9).trimmed() );
1474 else if( line.startsWith("Recommends:") )
1476 pkg->appendRecommends( line.mid(11).trimmed() );
1478 else if( line.startsWith("Suggests:") )
1480 pkg->appendSuggests( line.mid(9).trimmed() );
1482 else if( line.startsWith("Provides:") )
1484 pkg->appendProvides( line.mid(9).trimmed() );
1486 else if( line.startsWith("Breaks:") )
1488 pkg->appendBreaks( line.mid(7).trimmed() );
1490 else if( line.startsWith("Maintainer:") )
1492 pkg->setMaintainer( line.mid(11).trimmed() );
1495 else if( line.startsWith("Description:") )
1497 pkg->setDescShort( line.mid(12).trimmed() );
1498 iMultiLine = MultiLineDesc;
1500 else if( line.startsWith("Maemo-Icon-26:") )
1502 if( line.mid(15).trimmed() != "" ) {
1503 pkg->appendIconData( line.mid(15).trimmed() );
1505 iMultiLine = MultiLineIcon;
1507 else if( line.startsWith("Maemo-Upgrade-Description:") )
1509 pkg->appendUpgradeDescription( line.mid(26).trimmed() + "\n" );
1510 iMultiLine = MultiLineUpgradeDesc;
1518 void AAptInterface::writeBlacklist()
1520 QHashIterator<QString, Package*> i( iPackagesAvailable );
1525 if( i.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1526 iBlacklist << i.value()->name();
1528 else if( i.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1529 iBlacklist << (i.value()->name() + " " + i.value()->version());
1533 QHashIterator<QString, Package*> j( iPackagesInstalled );
1538 if( j.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1539 iBlacklist << j.value()->name();
1541 else if( j.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1542 iBlacklist << (j.value()->name() + " " + j.value()->version());
1546 iBlacklist.removeDuplicates();
1548 QFile f( KBlacklistFile );
1549 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1551 QTextStream out(&f);
1552 for( int i=0; i<iBlacklist.count(); i++ )
1553 out << iBlacklist.at(i) << "\n";
1557 qDebug() << "blacklist: wrote" << iBlacklist.count() << "entries";
1560 void AAptInterface::readBlacklist()
1562 QFile f( KBlacklistFile );
1563 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1565 while( !f.atEnd() ) {
1566 QString line = f.readLine().trimmed();
1568 iBlacklist.append(line);
1573 iBlacklist.removeDuplicates();
1575 qDebug() << "blacklist: read" << iBlacklist.count() << "entries";
1577 for( int i=0; i<iBlacklist.count(); i++ )
1579 QStringList parts = iBlacklist.at(i).split(' ');
1580 Package* pkg = iPackagesAvailable.value(parts.at(0).trimmed(), 0);
1581 Package* pkg2 = iPackagesInstalled.value(parts.at(0).trimmed(), 0);
1582 if( parts.count()==1 ) {
1584 pkg->setBlacklisted(BlacklistSelect::BlacklistAll);
1586 pkg2->setBlacklisted(BlacklistSelect::BlacklistAll);
1587 } else if( parts.count()==2 ) {
1588 if( pkg && pkg->version()==parts.at(1) )
1589 pkg->setBlacklisted(BlacklistSelect::BlacklistThis);
1590 if( pkg2 && pkg2->version()==parts.at(1) )
1591 pkg2->setBlacklisted(BlacklistSelect::BlacklistThis);
1593 qDebug() << "Warning: invalid blacklist entry:" << iBlacklist.at(i);
1598 void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList oldstate)
1601 qDebug() << "Warning: trying to remove null package from blacklist";
1605 QStringList newlist;
1606 bool removed = false;
1608 for( int i=0; i<iBlacklist.count(); i++ )
1610 if( oldstate == BlacklistSelect::BlacklistAll )
1612 if( !(iBlacklist.at(i) == pkg->name()) ) {
1613 newlist << iBlacklist.at(i);
1614 } else removed = true;
1615 } else if( oldstate == BlacklistSelect::BlacklistThis ) {
1616 if( !(iBlacklist.at(i) == (pkg->name()+" "+pkg->version())) ) {
1617 newlist << iBlacklist.at(i);
1618 } else removed = true;
1623 qDebug() << "blacklist: removed" << pkg->name();
1625 qDebug() << "blacklist:" << pkg->name() << "not in saved list";
1627 iBlacklist = newlist;
1631 void AAptInterface::startFetchDates()
1633 logToFile( QString("Start fetching package dates") );
1634 qDebug() << "start fetching package dates";
1636 if( !iNeedDateRefresh || iSkipRefreshListAndDates ) {
1637 qDebug() << "no need to fetch dates";
1638 logToFile( QString("No need to fetch dates") );
1639 communicateStatusToUi(true, "Operation finished", "Date information already up to date");
1645 iUiDimmer->updateText("Reading date cache");
1646 iUiDimmer->setProgress(0);
1647 QApplication::processEvents();
1653 iUiDimmer->updateText("Fetching package date information");
1654 QApplication::processEvents();
1657 QNetworkAccessManager* nam = new QNetworkAccessManager(this);
1659 if( iSettings->qsettings()->value("use_proxies").toBool() && !iSettings->qsettings()->value("http_proxy").toString().isEmpty() )
1661 QNetworkProxy proxy = Settings::createProxyFromString( iSettings->qsettings()->value("http_proxy").toString() );
1662 nam->setProxy(proxy);
1668 int updProgress = 0;
1670 QHash<QString, Package*> fetchable;
1671 QHashIterator<QString, Package*> i( iPackagesAvailable );
1672 while (i.hasNext() )
1675 if( !i.value()->date().isValid() && i.value()->section().startsWith("user/") && !i.value()->isBlacklisted() )
1677 const Repository* repo = 0;
1678 for( int x=0; x<i.value()->repositories().count(); x++ ) {
1679 if( i.value()->repositories().at(x) && i.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1681 repo = i.value()->repositories().at(x);
1686 fetchable.insert(i.value()->name(), i.value());
1691 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(dateFetchNetworkReply(QNetworkReply*)));
1692 iDateRequestsWaiting = 0;
1693 iDateRequestsSent = 0;
1694 iDateRequestsReceived = 0;
1695 iNetworkError = QNetworkReply::NoError;
1697 QString dbgcount = QString("need to fetch date for %1 packages").arg(fetchable.count());
1698 qDebug() << dbgcount;
1699 logToFile(dbgcount);
1701 QHashIterator<QString, Package*> fe( fetchable );
1702 while (fe.hasNext() && !iTerminated)
1706 if( updProgress >=20 ) {
1707 iUiDimmer->setProgress( count*100/fetchable.count() );
1711 if( !fe.value()->date().isValid() && fe.value()->section().startsWith("user/") && !fe.value()->isBlacklisted() )
1714 const Repository* repo = 0;
1715 QString fullFilename = "unknown_filename";
1716 for( int x=0; x<fe.value()->repositories().count(); x++ ) {
1717 if( fe.value()->repositories().at(x) && fe.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1719 repo = fe.value()->repositories().at(x);
1720 if( repo && fe.value()->fullFileNames().count()>x )
1721 fullFilename = fe.value()->fullFileNames().at(x);
1728 url = repo->url() + repo->dir() + fullFilename + "#" + fe.value()->name();
1730 //qDebug() << "getting date for" << fe.value()->name();
1734 QNetworkRequest r(u);
1736 if( iDateRequestsReceived == 0 ) {
1737 while( iDateRequestsWaiting>0 ) {
1738 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1741 while( iDateRequestsWaiting>50 ) {
1742 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1746 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1747 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1749 qDebug() << "fatal network error, aborting fetch";
1750 logToFile(QString("Fatal network error, date fetch aborted"));
1754 iDateRequestsSent++;
1755 iDateRequestsWaiting++;
1758 count = iDateRequestsReceived;
1762 while( iDateRequestsWaiting>0 ) {
1763 if( updProgress >=20 ) {
1764 iUiDimmer->setProgress( count*100/fetchable.count() );
1767 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1768 count = iDateRequestsReceived;
1774 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1775 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1777 // don't stop on this error, only inform the user
1778 iMainWindow->notifyDialog("Network error", "There was a network error while fetching date information, the fetch was aborted");
1783 iUiDimmer->setProgress(-1);
1785 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1791 iUiDimmer->setProgress(100);
1792 QApplication::processEvents();
1795 QString dbgstr = QString("sent %1 requests, received %2 replies with %3 errors").arg(iDateRequestsSent).arg(iDateRequestsReceived).arg(iDateRequestErrors);
1800 logToFile( QString("Finished fetching package dates") );
1802 if( fetchable.count()>0 || !dateCacheExists() ) {
1803 iUiDimmer->updateText("Writing date cache");
1804 QApplication::processEvents();
1809 iUiDimmer->updateText("Creating package view");
1810 QApplication::processEvents();
1811 iUiDimmer->setProgress(-1);
1814 communicateStatusToUi(true, "Operation finished", "Package dates fetched");
1815 iNeedDateRefresh = false;
1819 void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
1821 iDateRequestsWaiting--;
1822 iDateRequestsReceived++;
1823 //qDebug() << "reply" << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
1824 iNetworkError = reply->error();
1826 if( reply->error() == QNetworkReply::NoError && reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().isValid() )
1828 QString pkgname = reply->url().fragment();
1829 //qDebug() << pkgname;
1831 if( pkgname.isEmpty() )
1832 qDebug() << "warning: empty packagename in reply";
1834 Package* pkg = iPackagesAvailable.value(pkgname, 0);
1836 pkg->setDate( reply->header(QNetworkRequest::LastModifiedHeader).toDateTime() );
1838 qDebug() << "warning: unknown packagename in reply:" << pkgname;
1842 if( reply->error() != QNetworkReply::NoError ) {
1843 QString dbg = reply->url().fragment() + QString(": error %1: ").arg(reply->error()) + reply->errorString();
1846 iDateRequestErrors++;
1848 reply->deleteLater();
1851 void AAptInterface::writeDateCache()
1853 qDebug() << "writing date cache";
1855 QFile f(KDateCacheFile);
1856 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1858 QTextStream out(&f);
1859 QHashIterator<QString, Package*> i( iPackagesAvailable );
1860 while (i.hasNext() )
1863 if( i.value()->date().isValid() && i.value()->section().startsWith("user/") )
1864 out << i.value()->name() << " " << i.value()->version() << " " << i.value()->date().toString(Qt::ISODate) << "\n";
1868 qDebug() << "Warning: failed to write date cache";
1869 logToFile(QString("Failed to write date cache"));
1873 void AAptInterface::readDateCache()
1875 qDebug() << "reading date cache";
1877 QFile f(KDateCacheFile);
1878 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1880 while( !f.atEnd() ) {
1881 QString line = f.readLine().trimmed();
1882 QStringList parts = line.split(' ');
1883 if( parts.count()==3 ) {
1884 Package* pkg = iPackagesAvailable.value(parts.at(0),0);
1885 if( pkg && pkg->section().startsWith("user/") && pkg->version()==parts.at(1) )
1887 QDateTime dt = QDateTime::fromString( parts.at(2), Qt::ISODate);
1888 if( dt.isValid() ) {
1891 qDebug() << "Warning: Invalid date in date cache";
1892 logToFile(QString("Invalid date in date cache"));
1896 qDebug() << "Warning: error in date cache:" << line;
1897 logToFile(QString("Error in date cache"));
1902 qDebug() << "date cache does not exist";
1906 bool AAptInterface::dateCacheExists()
1908 QFileInfo f(KDateCacheFile);
1912 void AAptInterface::readPinnedPackages()
1914 QFile f(KAptPreferencesFile);
1918 bool warnAllPinned = false;
1919 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1921 qDebug() << "apt preferences exist: reading pinned packages";
1922 int pinned_packages = 0;
1925 QString line = f.readLine().trimmed();
1927 if( line=="Package: *" || line=="Package:*")
1928 warnAllPinned = true;
1930 if( line.startsWith("Package:") ) {
1932 QString pkg = line.mid(8).trimmed();
1933 Package* pkg_i = iPackagesInstalled.value(pkg,0);
1935 pkg_i->setPinned(true);
1937 Package* pkg_a = iPackagesAvailable.value(pkg,0);
1939 pkg_a->setPinned(true);
1944 qDebug() << "read" << pinned_packages << "pinned packages";
1947 if( warnAllPinned ) {
1948 iMainWindow->notifyDialog("Warning","You have pinned packages with '*' in apt preferences. It is strongly recommended to "
1949 "remove such settings as they can result in unexpected behavior of Faster Application Manager.");
1953 bool AAptInterface::loadInstallFiles(QStringList files_)