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);
92 AAptInterface::~AAptInterface()
94 if( iProcAptGetUpdate->state() != QProcess::NotRunning )
95 iProcAptGetUpdate->kill();
96 if( iProcAptGetSimulate->state() != QProcess::NotRunning )
97 iProcAptGetSimulate->kill();
98 if( iProcAptGetInstall->state() != QProcess::NotRunning )
99 iProcAptGetInstall->kill();
100 if( iProcAptGetClean->state() != QProcess::NotRunning )
101 iProcAptGetClean->kill();
103 // qprocesses are automatically deleted by their parent
105 QHashIterator<QString, Package*> a( iPackagesAvailable );
111 iPackagesAvailable.clear();
113 QHashIterator<QString, Package*> i( iPackagesInstalled );
119 iPackagesInstalled.clear();
121 for(int x=0; x<iRepositories.count(); x++) {
122 if( iRepositories.at(x) )
123 delete iRepositories.at(x);
125 iRepositories.clear();
127 delete[] iDataReadBuffer;
131 void AAptInterface::addQueuedOperation(interfaceMode mode_)
133 iOperationsQueue.append( mode_ );
136 void AAptInterface::setNeedRefresh(int repos, int lists, int dpkg, int dates)
138 if( repos==0 || repos==1 )
139 iNeedRepoRefresh = (bool)repos;
140 if( lists==0 || lists==1 )
141 iNeedListRefresh = (bool)lists;
142 if( dpkg==0 || dpkg==1 )
143 iNeedDpkgRefresh = (bool)dpkg;
144 if( dates==0 || dates==1 )
145 iNeedDateRefresh = (bool)dates;
148 bool AAptInterface::needListOrDateRefresh()
150 if( iNeedListRefresh || iNeedDpkgRefresh || iNeedDateRefresh )
156 bool AAptInterface::run(dimmer* uiDimmer)
158 if( iMode != ModeNone ) {
159 //qDebug() << "Can't run: not ModeNone";
163 if( iOperationsQueue.count() == 0 ) {
164 qDebug() << "Can't run: Queue empty";
168 iUiDimmer = uiDimmer;
169 iQueueMessages.clear();
177 void AAptInterface::runNext()
179 if( iOperationsQueue.count()==0 ) {
190 iMode = iOperationsQueue.takeAt(0);
191 iModeLog.append(iMode);
193 if( iMode == ModeAptGetUpdate ) {
194 if( !startAptGetUpdate() )
195 errorAptGetUpdate( QProcess::FailedToStart );
197 if( iMode == ModeAptGetInstall ) {
198 if( !startAptGetInstall() )
199 errorAptGetInstall( QProcess::FailedToStart );
201 if( iMode == ModeAptGetSimulate ) {
202 if( !startAptGetSimulate() )
203 errorAptGetSimulate( QProcess::FailedToStart );
205 if( iMode == ModeAptGetClean ) {
206 if( !startAptGetClean() )
207 errorAptGetClean( QProcess::FailedToStart );
209 if( iMode == ModeFetchDates )
212 if( iMode == ModeReadPackages )
216 void AAptInterface::cleanAfterRunEach()
224 void AAptInterface::cleanAfterRunAll()
228 iSkipRefreshListAndDates = false;
231 void AAptInterface::cleanAfterError()
234 iOperationsQueue.clear();
235 iProcessPackages.clear();
236 iProcessPackagesOrig.clear();
237 iProcessPackageVersions.clear();
240 bool AAptInterface::running() const
242 if( iMode == ModeNone )
247 bool AAptInterface::cancel()
249 // should return false if can't cancel, or terminate the running process (and clear queue) otherwise
250 if( iMode == ModeNone )
257 if( iMode == ModeAptGetUpdate ) {
258 if( iProcAptGetUpdate->state() == QProcess::Running )
259 iProcAptGetUpdate->terminate();
264 iNeedRepoRefresh = true;
267 if( iMode == ModeAptGetSimulate ) {
268 if( iProcAptGetSimulate->state() == QProcess::Running )
269 iProcAptGetSimulate->terminate();
276 if( iMode == ModeAptGetInstall ) {
277 if( iProcAptGetInstall->state() == QProcess::Running )
278 iProcAptGetInstall->terminate();
285 if( iMode == ModeReadPackages ) {
289 if( iMode == ModeFetchDates ) {
296 bool AAptInterface::startAptGetUpdate()
299 iProcAptGetUpdateOutput.clear();
301 if( !this->writeRepositories() )
303 iNeedListRefresh = true;
304 iNeedDpkgRefresh = true;
305 iNeedDateRefresh = true;
308 iUiDimmer->setProgress(0);
309 iUiDimmer->updateText("Updating catalogs");
314 for( int i=0; i<iRepositories.count(); i++ ) {
315 if( iRepositories.at(i) && iRepositories.at(i)->enabled() ) {
317 QStringList comp = iRepositories.at(i)->components().split(' ');
318 iCatalogsTotal += comp.count();
322 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
323 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
324 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
325 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
327 if( http_proxy != "" )
328 env.insert("http_proxy", http_proxy);
329 if( https_proxy != "" )
330 env.insert("https_proxy", https_proxy);
332 iProcAptGetUpdate->setProcessEnvironment(env);
334 QString runBinary = "/usr/bin/apt-get";
335 QStringList runParameters;
336 runParameters << "-q" << "update"
337 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
338 << "-o" << "Dir::State::lists=" + KAptListDir
339 << "-o" << "Dir::Etc::sourceparts=\"\"";
340 logToFile( runBinary + " " + runParameters.join(" ") );
341 iProcAptGetUpdate->start(runBinary,runParameters);
346 bool AAptInterface::startAptGetSimulate()
348 if( iProcessPackages.count()==0 )
353 iUiDimmer->updateText("Reading dependencies");
356 QString runBinary = "/usr/bin/apt-get";
357 QStringList runParameters;
358 runParameters << "-qsy" << "--allow-unauthenticated"
359 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
360 << "-o" << "Dir::State::lists=" + KAptListDir
361 << "-o" << "Dir::Etc::sourceparts=\"\"";
362 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
363 runParameters << "--auto-remove";
364 runParameters << "install";
365 runParameters << iProcessPackages;
367 logToFile( runBinary + " " + runParameters.join(" ") );
368 iProcAptGetSimulate->start(runBinary,runParameters);
373 bool AAptInterface::startAptGetInstall()
375 if( iProcessPackages.count()==0 )
378 iNeedListRefresh = true;
379 iNeedDpkgRefresh = true;
381 iProcAptGetInstallOutput.clear();
383 qDebug() << "running apt-get install";
385 QString runBinary = "/usr/bin/apt-get";
386 QStringList runParameters;
387 runParameters << "-qy" << "--allow-unauthenticated"
388 << "-o" << "DPkg::options::=--force-confnew"
389 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
390 << "-o" << "Dir::State::lists=" + KAptListDir
391 << "-o" << "Dir::Etc::sourceparts=\"\"";
392 if( iSettings->qsettings()->value("enable_autoremove", true).toBool() )
393 runParameters << "--auto-remove";
394 runParameters << "install";
395 runParameters << iProcessPackagesOrig;
399 for( int i=0; i<iProcessPackages.count(); i++) {
400 if( iProcessPackages.at(i).endsWith('-') )
406 iAptGetDownloadCount = 0;
407 iAptGetInstallCount = 0;
408 iAptGetRemoveCount = 0;
409 iAptGetInstallTotal = inst_count;
410 iAptGetRemoveTotal = remv_count;
411 iAptGetCurrentFileDownloadSize = 0;
412 iAptGetCurrentFileTotalSize = 0;
413 iAptGetCurrentDownloadFileName = "";
414 iProgressCheckTimer = 0;
417 iUpdateSpeed = false;
419 bool useproxy = iSettings->qsettings()->value("use_proxies",false).toBool();
420 QString http_proxy = iSettings->qsettings()->value("http_proxy","").toString();
421 QString https_proxy = iSettings->qsettings()->value("https_proxy","").toString();
422 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
424 if( http_proxy != "" )
425 env.insert("http_proxy", http_proxy);
426 if( https_proxy != "" )
427 env.insert("https_proxy", https_proxy);
429 env.insert("DEBIAN_FRONTEND", "noninteractive");
430 iProcAptGetUpdate->setProcessEnvironment(env);
432 logToFile( runBinary + " " + runParameters.join(" ") );
433 iProcAptGetInstall->start(runBinary,runParameters);
438 bool AAptInterface::startAptGetClean()
440 QString runBinary = "/usr/bin/apt-get";
441 QStringList runParameters;
443 << "-o" << "Dir::Etc::sourcelist=" + KAptSourceList
444 << "-o" << "Dir::State::lists=" + KAptListDir
445 << "-o" << "Dir::Etc::sourceparts=\"\""
449 iUiDimmer->updateText("Cleaning package cache");
452 logToFile( runBinary + " " + runParameters.join(" ") );
453 iProcAptGetClean->start(runBinary,runParameters);
458 QString AAptInterface::setQProcessErrorMessage(QProcess::ProcessError error)
461 logToFile(QString("Cancelled by user - terminating process"));
462 return "Cancelled by user";
464 else if( error == QProcess::FailedToStart )
465 return "Process failed to start";
466 else if( error == QProcess::Crashed )
467 return "Process crashed";
468 else if( error == QProcess::ReadError )
469 return "QProcess read error";
470 else if( error == QProcess::WriteError )
471 return "QProcess write error";
472 else if( error == QProcess::Timedout )
473 return "QProcess timeout error";
474 else if( error == QProcess::UnknownError )
475 return "QProcess unknown error";
477 return "Unknown error";
480 void AAptInterface::errorAptGetUpdate(QProcess::ProcessError error)
482 QString msg = setQProcessErrorMessage(error);
485 iUiDimmer->setProgress(-1);
487 communicateStatusToUi(false, "Error", msg);
489 iNeedRepoRefresh = true;
493 void AAptInterface::errorAptGetSimulate(QProcess::ProcessError error)
495 QString msg = setQProcessErrorMessage(error);
496 iProcessPackages.clear();
497 iProcessPackagesOrig.clear();
498 iProcessPackageVersions.clear();
500 communicateStatusToUi(false, "Error", msg);
505 void AAptInterface::errorAptGetInstall(QProcess::ProcessError error)
507 QString msg = setQProcessErrorMessage(error);
508 iProcessPackages.clear();
509 iProcessPackagesOrig.clear();
510 iProcessPackageVersions.clear();
512 if( iProgressCheckTimer ) {
513 iProgressCheckTimer->stop();
514 delete iProgressCheckTimer;
515 iProgressCheckTimer = 0;
518 iUiDimmer->setProgress(-1);
521 communicateStatusToUi(false, "Error", msg);
526 void AAptInterface::errorAptGetClean(QProcess::ProcessError error)
528 QString msg = setQProcessErrorMessage(error);
530 communicateStatusToUi(false, "Error", msg);
535 QString AAptInterface::finishProcessCommonErrorMessages(QByteArray& output)
537 QString msg = "Unknown error - see the log for details";
539 if( output.contains("Could not get lock") || output.contains("Could not open lock file") ) {
540 msg = "The package management system is locked by another process or permission was denied";
541 } else if( output.contains("E: Unable to fetch some archives") ) {
542 msg = "Failed to fetch packages - Your network connection might be down or your catalogs could be out of date";
543 } else if( output.contains("E: Couldn't find package") ) {
544 msg = "Missing package, see the log for details - Your catalogs might be out of date";
545 } else if( output.contains("E: Broken packages") ) {
546 msg = "Your system has broken packages or you are trying to install conflicting packages. See the log for details.";
547 } else if( output.contains("E: Handler silently failed") ) {
548 msg = "Handler silently failed - This can happen if you try to install from the forbidden user/hidden category. Disabling OVI store repositories might help.";
549 } else if( iTerminated ) {
550 msg = "The operation was cancelled by user";
551 } else if( output.contains("Temporary failure resolving") || output.contains("Could not resolve host") ) {
552 msg = "DNS errors were reported, check your network connection and/or repository configuration";
553 } else if( output.contains("E: dpkg was interrupted") ) {
554 msg = "Your system has partially installed or broken packages. You'll have to fix this manually. Try dpkg --configure -a";
555 } else if( output.contains("dpkg: error processing") || output.contains("Errors were encountered while processing:") ) {
556 msg = "dpkg reported errors while processing a package - see the log for details";
557 } else if( output.contains("E: Unmet dependencies") ) {
558 msg = "Some of your packages have unmet dependencies which could not be fixed. See the log for details.";
559 } else if( output.contains("E: The method driver") ) {
560 msg = "Apt failed to find a suitable method driver. One or more of your repositories might have an invalid URL.";
561 } else if( output.contains("E: Invalid record in the preferences file") ) {
562 msg = "Invalid record in the apt preferences file.";
563 } else if( output.contains("E: Malformed line") && output.contains("in source list") ) {
564 msg = "Malformed line in sources list. Check your repository settings.";
570 void AAptInterface::finishedAptGetUpdate(int exitCode, QProcess::ExitStatus exitStatus)
572 //QByteArray output = iProcAptGetUpdate->readAllStandardOutput();
573 //logToFile( "Output from last process:\n---\n"+output );
577 iProcAptGetUpdate->close();
582 QString title = "Operation finished";
583 QString msg = "Catalogs updated";
584 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
588 msg = finishProcessCommonErrorMessages(iProcAptGetUpdateOutput);
592 iUiDimmer->setProgress(-1);
594 if( iProcAptGetUpdateOutput.contains("Could not resolve ") || iProcAptGetUpdateOutput.contains("W: Failed to fetch") ||
595 iProcAptGetUpdateOutput.contains("Temporary failure resolving") ) {
598 msg = "Failed to update some or all of the catalogs. Check your network connection and/or repository configuration";
602 iNeedRepoRefresh = false;
604 QFile lastupdate(KLastUpdateFile); // create an empty file and/or update the modification time
605 if( lastupdate.open(QIODevice::WriteOnly) )
608 int pos = iProcAptGetUpdateOutput.indexOf("\nFetched ");
610 msg += "<br>apt-get: ";
611 msg += iProcAptGetUpdateOutput.mid(pos+1, iProcAptGetUpdateOutput.indexOf('\n', pos+1)-pos ).trimmed();
618 iProcAptGetUpdate->close();
619 communicateStatusToUi(success, title, msg);
623 void AAptInterface::finishedAptGetSimulate(int exitCode, QProcess::ExitStatus exitStatus)
625 QByteArray output = iProcAptGetSimulate->readAllStandardOutput();
626 logToFile( "Output from last process:\n---\n"+output );
630 iProcAptGetSimulate->close();
635 QString title = "Operation finished";
637 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
641 msg = finishProcessCommonErrorMessages(output);
644 iProcessPackages.clear();
645 iProcessPackageVersions.clear();
648 QList<QByteArray> lines = output.split('\n');
650 for( int i=0; i<lines.count(); i++)
652 QString s = lines.at(i);
653 if( s.startsWith("Inst ") )
655 iProcessPackages << s.section(' ',1,1);
659 int a1 = s.indexOf('[');
660 int a2 = s.indexOf(']');
661 if( a1!=-1 && a2!=-1 && a2>a1) {
662 vs = s.mid(a1+1, a2-a1-1) + " -> ";
664 int b1 = s.indexOf('(');
665 int b2 = s.indexOf(' ',b1);
666 if( b1!=-1 && b2!=-1 && b2>b1) {
667 vs += s.mid(b1+1, b2-b1-1);
670 iProcessPackageVersions << vs;
672 if( s.startsWith("Remv ") )
674 iProcessPackages << s.section(' ',1,1) + "-";
677 int a1 = s.indexOf('[');
678 int a2 = s.indexOf(']');
679 if( a1!=-1 && a2!=-1 && a2>a1) {
680 vs = s.mid(a1+1, a2-a1-1);
683 iProcessPackageVersions << vs;
690 iProcAptGetSimulate->close();
691 communicateStatusToUi(success, title, msg);
695 void AAptInterface::finishedAptGetInstall(int exitCode, QProcess::ExitStatus exitStatus)
697 //QByteArray output = iProcAptGetInstall->readAllStandardOutput();
698 //logToFile( "Output from last process:\n---\n"+output );
701 iProcAptGetInstall->close();
707 QString title = "Operation finished";
708 QString msg = "Package operations finished successfully";
709 if( exitCode != 0 || exitStatus == QProcess::CrashExit || iTerminated )
713 msg = finishProcessCommonErrorMessages(iProcAptGetInstallOutput);
716 if( iProgressCheckTimer ) {
717 iProgressCheckTimer->stop();
718 delete iProgressCheckTimer;
719 iProgressCheckTimer = 0;
722 iUiDimmer->setProgress(-1);
724 iProcessPackages.clear();
725 iProcessPackagesOrig.clear();
726 iProcessPackageVersions.clear();
731 iProcAptGetInstall->close();
732 communicateStatusToUi(success, title, msg);
736 void AAptInterface::finishedAptGetClean(int exitCode, QProcess::ExitStatus exitStatus)
738 QByteArray output = iProcAptGetClean->readAllStandardOutput();
739 // this should produce no output
740 //logToFile( "Output from last process:\n---\n"+output );
744 iProcAptGetClean->close();
749 QString title = "Operation finished";
750 QString msg = "Package cache cleaned";
751 if( exitCode != 0 || exitStatus == QProcess::CrashExit )
755 msg = finishProcessCommonErrorMessages(output);
760 iProcAptGetClean->close();
761 communicateStatusToUi(success, title, msg);
766 void AAptInterface::uiUpdaterAptGetUpdate()
768 QByteArray data = iProcAptGetUpdate->read( iProcAptGetUpdate->bytesAvailable() );
769 logToFile( data, false );
770 iProcAptGetUpdateOutput.append(data);
775 QStringList lines = QString( data.trimmed() ).split('\n');
778 for( int i=0; i<lines.count(); i++ )
780 if( lines.at(i).startsWith("Get:") || lines.at(i).startsWith("Hit ") )
784 infoline = lines.at(i).trimmed();
786 //if( infoline.isEmpty() )
787 //infoline = "arstus";
789 //iUiDimmer->updateText( QString("Updating catalogs (%1)").arg(iCatalogCounter) );
790 //qDebug() << iCatalogCounter << iCatalogsTotal;
792 //iUiDimmer->updateText("Updating catalogs<br><font size=\"-1\">" + infoline + "</font>");
794 if( iCatalogsTotal > 0 )
795 iUiDimmer->setProgress( iCatalogCounter*100/iCatalogsTotal );
798 void AAptInterface::uiUpdaterAptGetInstall()
800 QByteArray data = iProcAptGetInstall->read( iProcAptGetInstall->bytesAvailable() );
801 logToFile( data, false );
802 iProcAptGetInstallOutput.append(data);
807 QStringList lines = QString( data.trimmed() ).split('\n');
810 bool resetprogress = true;
812 QString pkgname = "";
814 for( int i=0; i<lines.count(); i++ )
816 QStringList l = lines.at(i).split(' ');
818 if( l.count()>=4 && l.at(0).startsWith("Get:") ) {
819 oper = "Downloading";
822 Package* pkg = iPackagesAvailable.value(pkgname,0);
824 iAptGetCurrentDownloadFileName = pkg->fileName();
825 iAptGetCurrentFileTotalSize = pkg->size()/1024;
826 pkgname += QString(" (%L1 kB)").arg(iAptGetCurrentFileTotalSize);
828 iAptGetDownloadCount++;
829 oper += QString(" %1/%2").arg(iAptGetDownloadCount).arg(iAptGetInstallTotal);
831 if( !iProgressCheckTimer ) {
832 iProgressCheckTimer = new QTimer(this);
833 connect(iProgressCheckTimer,SIGNAL(timeout()),this,SLOT(progressCheckTimerCallback()));
834 iProgressCheckTimer->start(500);
836 resetprogress = false;
837 } else if( l.count()>=2 && l.at(0)=="Unpacking") {
839 if( l.count()>=3 && l.at(1)=="replacement" )
843 iAptGetInstallCount++;
844 oper += QString(" %1/%2").arg(iAptGetInstallCount).arg(iAptGetInstallTotal);
846 } else if( l.count()>=3 && l.at(0)=="Setting" && l.at(1)=="up") {
849 } else if( l.count()>=2 && l.at(0)=="Removing") {
852 iAptGetRemoveCount++;
853 oper += QString(" %1/%2").arg(iAptGetRemoveCount).arg(iAptGetRemoveTotal);
855 } else if( l.count()>=1 && l.at(0)=="Done!") {
856 oper = "Setting up...";
861 /* // this does not seem to work, dpkg always dies first
862 if( lines.at(i).startsWith("***") && lines.at(i).contains("(Y/I/N/O/D/Z)") ) {
863 if( iMainWindow->confirmDialog("Overwrite configuration file?","la la la") )
865 iProcAptGetInstall->write("Y\n");
867 iProcAptGetInstall->write("N\n");
873 if( update && iUiDimmer && iUiDimmer->busy() ) {
874 iUiDimmer->updateText( oper + "<br>" + pkgname );
875 if( resetprogress ) {
876 iUiDimmer->setProgress(-1);
877 if( iProgressCheckTimer ) {
878 iProgressCheckTimer->stop();
879 delete iProgressCheckTimer;
880 iProgressCheckTimer = 0;
886 void AAptInterface::progressCheckTimerCallback()
888 if( iAptGetCurrentDownloadFileName.isEmpty() )
891 qint64 prevsize = iAptGetCurrentFileDownloadSize;
892 QFile pkgfile(KAptArchivePartialDir + "/" + iAptGetCurrentDownloadFileName);
893 iAptGetCurrentFileDownloadSize = pkgfile.size()/1024;
895 if( iAptGetCurrentFileDownloadSize >= prevsize ) {
896 iSpeedKbpsPrev = iSpeedKbps;
897 iSpeedKbps = (iAptGetCurrentFileDownloadSize-prevsize)*2;
902 iUpdateSpeed = false;
906 if( iUiDimmer && iUiDimmer->busy() ) {
907 int p = iAptGetCurrentFileDownloadSize*100/iAptGetCurrentFileTotalSize;
908 if( iAptGetDownloadCount > 0 && iAptGetCurrentFileDownloadSize==0 )
910 iUiDimmer->setProgress( p );
911 if( iSpeedKbps>=0 && iSpeedKbpsPrev>=0 && iUpdateSpeed ) {
912 iUiDimmer->setDownloadSpeed( (iSpeedKbps+iSpeedKbpsPrev)/2 );
918 void AAptInterface::communicateStatusToUi(bool success, QString title, QString msg)
920 qDebug() << title << msg;
921 iQueueMessages.append(msg);
923 if( iMainWindow && iOperationsQueue.count()==0 )
925 // title comes from the last finished operation only
926 iMainWindow->operationQueueFinished(iModeLog, success, title, iQueueMessages);
930 QByteArray AAptInterface::readLogFile()
935 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
939 QByteArray line = own.readLine();
946 log = "The log is empty";
951 void AAptInterface::logToFile( QString data, bool logtime )
953 logToFile( data.toAscii(), logtime );
956 void AAptInterface::logToFile( QByteArray data, bool logtime )
960 if( f.open( QIODevice::Append | QIODevice::WriteOnly | QIODevice::Text ) )
964 out << "--- " << QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") << " ---\n";
974 void AAptInterface::readRepositoryInfo()
976 for(int i=0; i<iRepositories.count(); i++) {
977 if( iRepositories.at(i) )
978 delete iRepositories.at(i);
980 iRepositories.clear();
981 bool ownFound = false;
983 QFile own( KOwnRepoFile );
984 if( own.open(QIODevice::ReadOnly | QIODevice::Text ) )
989 QString line = own.readLine().trimmed();
990 if( line.startsWith("deb ") || line.startsWith("#deb ") )
992 r = new Repository();
993 if( r->setFromString(line) ) {
994 iRepositories.append(r);
995 //qDebug() << r->toListFileNames();
1003 if( iRepositories.count() > 0 )
1007 QFile names( KOwnRepoNamesFile );
1008 if( names.open(QIODevice::ReadOnly | QIODevice::Text ) )
1011 while(!names.atEnd() && c<iRepositories.count())
1013 QString line = names.readLine().trimmed();
1014 if( !line.trimmed().isEmpty() )
1015 iRepositories.at(c)->setName( line.trimmed() );
1023 qDebug() << "own repo lists found";
1027 QFile ham( KHamRepoListFile );
1028 if( ham.open(QIODevice::ReadOnly | QIODevice::Text ) )
1032 QString line = ham.readLine();
1033 Repository* r = new Repository();
1034 if( r->setFromString(line) ) {
1035 iRepositories.append(r);
1038 // disable the ovi repository by default
1039 if( line.contains("https://downloads.maemo.nokia.com/fremantle1.2/ovi/") ) {
1040 r->setEnabled(false);
1049 qDebug() << "system repo list loaded";
1054 bool AAptInterface::writeRepositories()
1056 iNeedListRefresh = true;
1058 QFile own( KOwnRepoFile );
1059 if( own.open(QIODevice::WriteOnly | QIODevice::Text ) )
1061 QTextStream out(&own);
1062 for( int i=0; i<iRepositories.count(); i++ )
1063 out << iRepositories.at(i)->toString() << "\n";
1067 QFile names( KOwnRepoNamesFile );
1068 if( names.open(QIODevice::WriteOnly | QIODevice::Text ) )
1070 QTextStream out(&names);
1071 for( int i=0; i<iRepositories.count(); i++ )
1072 out << iRepositories.at(i)->name() << "\n";
1076 QFile ham( KAptSourceList );
1077 if( ham.open(QIODevice::WriteOnly | QIODevice::Text ) )
1079 QTextStream out(&ham);
1080 for( int i=0; i<iRepositories.count(); i++ )
1081 out << iRepositories.at(i)->toString() << "\n";
1086 qDebug() << "Failed to write repository list!";
1092 bool AAptInterface::needRepoRefresh()
1094 if( iNeedRepoRefresh || iSettings->qsettings()->value("need_repo_refresh", false).toBool() ) {
1095 iNeedRepoRefresh = false;
1096 iSettings->qsettings()->setValue("need_repo_refresh", false);
1097 qDebug() << "repo update required, debug 1";
1101 QFile own(KAptSourceList);
1105 qDebug() << "repo update required, debug 2";
1109 QFileInfo a(KLastUpdateFile);
1113 aDate = a.lastModified();
1115 qDebug() << "repo update required, debug 3";
1118 aDate = aDate.addSecs(24*60*60); //24h
1120 if( aDate < QDateTime::currentDateTime() ) {
1121 qDebug() << "repo update required, debug 4";
1125 qDebug() << "repo update not required";
1131 void AAptInterface::startPkgListRead()
1133 logToFile( QString("Start reading package lists") );
1134 qDebug() << "reading package list files";
1136 if( !iNeedListRefresh && !iNeedDpkgRefresh ) {
1137 qDebug() << "no need to refresh package lists";
1138 logToFile( QString("No need to read package lists") );
1139 communicateStatusToUi(true, "Operation finished", "Package data already up to date");
1145 iUiDimmer->updateText("Reading package lists<br>");
1146 iUiDimmer->setProgress(0);
1149 // clear packages lists
1150 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1152 QHashIterator<QString, Package*> a( iPackagesAvailable );
1158 iPackagesAvailable.clear();
1161 if( iNeedDpkgRefresh )
1163 QHashIterator<QString, Package*> i( iPackagesInstalled );
1169 iPackagesInstalled.clear();
1172 // read apt database (available packages)
1174 time_aptread.start();
1176 int pkgcount_apt = 0;
1177 QDir dir( KAptListDir );
1178 QFileInfoList files = dir.entryInfoList();
1180 quint64 totaldatasize = 0;
1181 quint64 currentreaddata = 0;
1182 quint64 lastupdatedata = 0;
1183 quint64 updateinterval = 2000000;
1184 if( iNeedListRefresh && !iSkipRefreshListAndDates ) {
1185 for( int i=0; i<files.count(); i++ )
1187 if( files.at(i).fileName().endsWith("_Packages"))
1188 totaldatasize += files.at(i).size();
1191 if( iNeedDpkgRefresh ) {
1192 QFileInfo dbinfo( KDpkgStatusFile );
1193 totaldatasize += dbinfo.size();
1197 if( iNeedListRefresh && !iSkipRefreshListAndDates )
1201 for( int i=0; i<files.count(); i++ )
1203 Repository* currentRepo = 0;
1204 if( files.at(i).absoluteFilePath().endsWith("_Packages") )
1207 for(int x=0; x<iRepositories.count(); x++) {
1208 if( iRepositories.at(x)->toListFileNames().contains( files.at(i).fileName() ) ) {
1209 currentRepo = iRepositories.at(x);
1213 if( iUiDimmer && currentRepo ) {
1214 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">" + currentRepo->name() + "</font>");
1217 //qDebug() << files.at(i).fileName();
1219 QFile db( files.at(i).absoluteFilePath() );
1220 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1221 qDebug() << "FAIL: Unable to read apt database";
1222 communicateStatusToUi(false, "Error", "Unable to read package lists");
1227 while (!db.atEnd() && !iTerminated) {
1228 Package* newpkg = ReadNextPackage(db, currentreaddata);
1229 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1230 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1231 lastupdatedata = currentreaddata;
1232 QApplication::processEvents();
1237 newpkg->addRepository( currentRepo );
1239 Package* exists = iPackagesAvailable.value(newpkg->name(),0);
1241 iPackagesAvailable.insert(newpkg->name(), newpkg);
1243 if( Package::versionCompare(newpkg->version(),exists->version()) )
1245 iPackagesAvailable.remove(exists->name());
1248 iPackagesAvailable.insert(newpkg->name(), newpkg);
1250 if( newpkg->version() == exists->version() ) {
1251 exists->addRepository( currentRepo );
1252 if( newpkg->fullFileNames().count()>0 )
1253 exists->addFullFileName( newpkg->fullFileNames().at(0) );
1255 exists->addFullFileName("unknown_dir/unknown_filename");
1267 qDebug() << "apt database read took" << time_aptread.elapsed() << "ms";
1268 qDebug() << "Processed" << filecount << "package list files";
1272 iUiDimmer->setProgress(-1);
1274 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1278 iNeedListRefresh = false;
1279 iNeedDateRefresh = true;
1280 iLastListUpdate = QDateTime::currentDateTime();
1283 // read dpkg database (installed packages)
1284 if( iNeedDpkgRefresh )
1287 QTime time_dpkgread;
1288 time_dpkgread.start();
1290 int pkgcount_dpkg = 0;
1291 QFile db( KDpkgStatusFile );
1292 if (!db.open(QIODevice::ReadOnly | QIODevice::Text)) {
1293 qDebug() << "FAIL: Unable to read dpkg database";
1294 communicateStatusToUi(false, "Error", "Unable to read package database");
1300 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">dpkg database</font>");
1303 while (!db.atEnd() && !iTerminated) {
1304 Package* newpkg = ReadNextPackage(db, currentreaddata);
1305 if( iUiDimmer && currentreaddata >= lastupdatedata+updateinterval ) {
1306 iUiDimmer->setProgress( currentreaddata*100/totaldatasize );
1307 lastupdatedata = currentreaddata;
1308 QApplication::processEvents();
1312 if( newpkg->isInstalled() && !newpkg->name().isEmpty() ) {
1313 iPackagesInstalled.insert(newpkg->name(), newpkg);
1322 qDebug() << "dpkg database read took" << time_dpkgread.elapsed() << "ms";
1324 qDebug() << "Processed" << pkgcount_apt << "(apt) and" << pkgcount_dpkg << "(dpkg) package entries";
1325 qDebug() << "In DB:" << iPackagesAvailable.count() << "packages available,"
1326 << iPackagesInstalled.count() << "installed";
1330 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1333 iNeedDpkgRefresh = false;
1334 iLastDpkgUpdate = QDateTime::currentDateTime();
1337 logToFile( QString("Finished reading package lists") );
1339 iUiDimmer->updateText("Reading package lists<br><font size=\"-1\">Creating package view</font>");
1340 QApplication::processEvents();
1341 iUiDimmer->setProgress(-1);
1345 readPinnedPackages();
1347 communicateStatusToUi(true, "Operation finished", "Package data read");
1352 Package* AAptInterface::ReadNextPackage(QFile& f, quint64& currentreaddata)
1354 iMultiLine=MultiLineNone;
1356 Package* pkg = new Package("", this);
1358 bool pkgready = false;
1360 // this is faster than directly reading to QByteArray...
1362 while( !pkgready && !f.atEnd() ) {
1363 f.readLine(iDataReadBuffer,KDataReadBufferSize);
1364 line = iDataReadBuffer;
1365 currentreaddata += line.size();
1366 if( processPackageDataLine(pkg,line) ) {
1371 if( !pkg->name().isEmpty() && pkg->isInstalled() ) {
1372 QFileInfo f( KDpkgInfoDir + "/" + pkg->name() + ".list" );
1374 pkg->setDate( f.lastModified() );
1377 pkg->updateStatus();
1379 if( pkg->name().isEmpty() ) {
1380 qDebug() << "null name package!";
1387 bool AAptInterface::processPackageDataLine(Package*& pkg, QByteArray& line)
1389 if( line.isEmpty() || line=="\n" )
1394 else if( iMultiLine == MultiLineDesc ) {
1395 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1396 if( line.trimmed()!="." )
1397 pkg->appendDescLong( line.trimmed() + "\n" );
1399 pkg->appendDescLong( "\n" );
1401 iMultiLine = MultiLineNone;
1404 else if( iMultiLine == MultiLineIcon ) {
1405 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1406 pkg->appendIconData( line.trimmed() );
1408 iMultiLine = MultiLineNone;
1411 else if( iMultiLine == MultiLineUpgradeDesc ) {
1412 if( (line.startsWith(' ') || line.startsWith('\t')) && !line.trimmed().isEmpty() ) {
1413 pkg->appendUpgradeDescription( line.trimmed() + "\n" );
1415 iMultiLine = MultiLineNone;
1419 else if( line.startsWith("Package:") )
1421 pkg->setName( line.mid(8).trimmed() );
1422 iMultiLine=MultiLineNone;
1424 else if( line.startsWith("Status:") )
1426 if( line.mid(7).trimmed() == "install ok installed" )
1427 pkg->setInstalled(true);
1429 pkg->setInstalled(false);
1431 else if( line.startsWith("Section:") )
1433 pkg->setSection( line.mid(8).trimmed() );
1435 else if( line.startsWith("Version:") )
1437 pkg->setVersion( line.mid(8).trimmed() );
1439 else if( line.startsWith("Filename:") )
1441 pkg->addFullFileName( line.mid(9).trimmed() );
1443 else if( line.startsWith("Size:") )
1445 pkg->setSize( line.mid(5).trimmed().toInt() );
1447 else if( line.startsWith("Installed-Size:") )
1449 pkg->setInstalledSize( line.mid(15).trimmed().toInt() );
1451 else if( line.startsWith("Maemo-Display-Name:") )
1453 pkg->setMaemoDisplayName( line.mid(19).trimmed() );
1455 else if( line.startsWith("Depends:") )
1457 pkg->appendDepends( line.mid(8).trimmed() );
1459 else if( line.startsWith("Conflicts:") )
1461 pkg->appendConflicts( line.mid(10).trimmed() );
1463 else if( line.startsWith("Pre-Depends:") )
1465 pkg->appendPreDepends( line.mid(12).trimmed() );
1467 else if( line.startsWith("Replaces:") )
1469 pkg->appendReplaces( line.mid(9).trimmed() );
1471 else if( line.startsWith("Recommends:") )
1473 pkg->appendRecommends( line.mid(11).trimmed() );
1475 else if( line.startsWith("Suggests:") )
1477 pkg->appendSuggests( line.mid(9).trimmed() );
1479 else if( line.startsWith("Provides:") )
1481 pkg->appendProvides( line.mid(9).trimmed() );
1483 else if( line.startsWith("Breaks:") )
1485 pkg->appendBreaks( line.mid(7).trimmed() );
1487 else if( line.startsWith("Maintainer:") )
1489 pkg->setMaintainer( line.mid(11).trimmed() );
1492 else if( line.startsWith("Description:") )
1494 pkg->setDescShort( line.mid(12).trimmed() );
1495 iMultiLine = MultiLineDesc;
1497 else if( line.startsWith("Maemo-Icon-26:") )
1499 if( line.mid(15).trimmed() != "" ) {
1500 pkg->appendIconData( line.mid(15).trimmed() );
1502 iMultiLine = MultiLineIcon;
1504 else if( line.startsWith("Maemo-Upgrade-Description:") )
1506 pkg->appendUpgradeDescription( line.mid(26).trimmed() + "\n" );
1507 iMultiLine = MultiLineUpgradeDesc;
1515 void AAptInterface::writeBlacklist()
1517 QHashIterator<QString, Package*> i( iPackagesAvailable );
1522 if( i.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1523 iBlacklist << i.value()->name();
1525 else if( i.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1526 iBlacklist << (i.value()->name() + " " + i.value()->version());
1530 QHashIterator<QString, Package*> j( iPackagesInstalled );
1535 if( j.value()->blacklisted() == BlacklistSelect::BlacklistAll ) {
1536 iBlacklist << j.value()->name();
1538 else if( j.value()->blacklisted() == BlacklistSelect::BlacklistThis ) {
1539 iBlacklist << (j.value()->name() + " " + j.value()->version());
1543 iBlacklist.removeDuplicates();
1545 QFile f( KBlacklistFile );
1546 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1548 QTextStream out(&f);
1549 for( int i=0; i<iBlacklist.count(); i++ )
1550 out << iBlacklist.at(i) << "\n";
1554 qDebug() << "blacklist: wrote" << iBlacklist.count() << "entries";
1557 void AAptInterface::readBlacklist()
1559 QFile f( KBlacklistFile );
1560 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1562 while( !f.atEnd() ) {
1563 QString line = f.readLine().trimmed();
1565 iBlacklist.append(line);
1570 iBlacklist.removeDuplicates();
1572 qDebug() << "blacklist: read" << iBlacklist.count() << "entries";
1574 for( int i=0; i<iBlacklist.count(); i++ )
1576 QStringList parts = iBlacklist.at(i).split(' ');
1577 Package* pkg = iPackagesAvailable.value(parts.at(0).trimmed(), 0);
1578 Package* pkg2 = iPackagesInstalled.value(parts.at(0).trimmed(), 0);
1579 if( parts.count()==1 ) {
1581 pkg->setBlacklisted(BlacklistSelect::BlacklistAll);
1583 pkg2->setBlacklisted(BlacklistSelect::BlacklistAll);
1584 } else if( parts.count()==2 ) {
1585 if( pkg && pkg->version()==parts.at(1) )
1586 pkg->setBlacklisted(BlacklistSelect::BlacklistThis);
1587 if( pkg2 && pkg2->version()==parts.at(1) )
1588 pkg2->setBlacklisted(BlacklistSelect::BlacklistThis);
1590 qDebug() << "Warning: invalid blacklist entry:" << iBlacklist.at(i);
1595 void AAptInterface::removeFromBlacklist(Package *pkg, BlacklistSelect::blackList oldstate)
1598 qDebug() << "Warning: trying to remove null package from blacklist";
1602 bool removed = false;
1604 for( int i=0; i<iBlacklist.count(); i++ )
1606 if( oldstate == BlacklistSelect::BlacklistAll )
1608 if( iBlacklist.at(i) == pkg->name() ) {
1609 iBlacklist.removeAt(i);
1613 } else if( oldstate == BlacklistSelect::BlacklistThis ) {
1614 if( iBlacklist.at(i) == (pkg->name()+" "+pkg->version()) ) {
1615 iBlacklist.removeAt(i);
1623 qDebug() << "blacklist: removed" << pkg->name();
1625 qDebug() << "blacklist:" << pkg->name() << "not in saved list";
1630 void AAptInterface::startFetchDates()
1632 logToFile( QString("Start fetching package dates") );
1633 qDebug() << "start fetching package dates";
1635 if( !iNeedDateRefresh || iSkipRefreshListAndDates ) {
1636 qDebug() << "no need to fetch dates";
1637 logToFile( QString("No need to fetch dates") );
1638 communicateStatusToUi(true, "Operation finished", "Date information already up to date");
1644 iUiDimmer->updateText("Reading date cache");
1645 iUiDimmer->setProgress(0);
1646 QApplication::processEvents();
1652 iUiDimmer->updateText("Fetching package date information");
1653 QApplication::processEvents();
1656 QNetworkAccessManager* nam = new QNetworkAccessManager(this);
1658 if( iSettings->qsettings()->value("use_proxies").toBool() && !iSettings->qsettings()->value("http_proxy").toString().isEmpty() )
1660 QNetworkProxy proxy = Settings::createProxyFromString( iSettings->qsettings()->value("http_proxy").toString() );
1661 nam->setProxy(proxy);
1667 int updProgress = 0;
1669 QHash<QString, Package*> fetchable;
1670 QHashIterator<QString, Package*> i( iPackagesAvailable );
1671 while (i.hasNext() )
1674 if( !i.value()->date().isValid() && i.value()->section().startsWith("user/") && !i.value()->isBlacklisted() )
1676 const Repository* repo = 0;
1677 for( int x=0; x<i.value()->repositories().count(); x++ ) {
1678 if( i.value()->repositories().at(x) && i.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1680 repo = i.value()->repositories().at(x);
1685 fetchable.insert(i.value()->name(), i.value());
1690 connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(dateFetchNetworkReply(QNetworkReply*)));
1691 iDateRequestsWaiting = 0;
1692 iDateRequestsSent = 0;
1693 iDateRequestsReceived = 0;
1694 iNetworkError = QNetworkReply::NoError;
1696 QString dbgcount = QString("need to fetch date for %1 packages").arg(fetchable.count());
1697 qDebug() << dbgcount;
1698 logToFile(dbgcount);
1700 QHashIterator<QString, Package*> fe( fetchable );
1701 while (fe.hasNext() && !iTerminated)
1705 if( updProgress >=20 ) {
1706 iUiDimmer->setProgress( count*100/fetchable.count() );
1710 if( !fe.value()->date().isValid() && fe.value()->section().startsWith("user/") && !fe.value()->isBlacklisted() )
1713 const Repository* repo = 0;
1714 QString fullFilename = "unknown_filename";
1715 for( int x=0; x<fe.value()->repositories().count(); x++ ) {
1716 if( fe.value()->repositories().at(x) && fe.value()->repositories().at(x)->url().startsWith("http://repository.maemo.org") )
1718 repo = fe.value()->repositories().at(x);
1719 if( repo && fe.value()->fullFileNames().count()>x )
1720 fullFilename = fe.value()->fullFileNames().at(x);
1727 url = repo->url() + repo->dir() + fullFilename + "#" + fe.value()->name();
1729 //qDebug() << "getting date for" << fe.value()->name();
1733 QNetworkRequest r(u);
1735 if( iDateRequestsReceived == 0 ) {
1736 while( iDateRequestsWaiting>0 ) {
1737 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1740 while( iDateRequestsWaiting>5 ) {
1741 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1745 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1746 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1748 qDebug() << "fatal network error, aborting fetch";
1749 logToFile(QString("Fatal network error, date fetch aborted"));
1753 iDateRequestsSent++;
1754 iDateRequestsWaiting++;
1757 count = iDateRequestsReceived;
1761 while( iDateRequestsWaiting>0 ) {
1762 if( updProgress >=20 ) {
1763 iUiDimmer->setProgress( count*100/fetchable.count() );
1766 QApplication::processEvents(QEventLoop::WaitForMoreEvents);
1767 count = iDateRequestsReceived;
1773 if( iDateRequestsReceived>0 && iNetworkError != QNetworkReply::NoError &&
1774 iNetworkError != QNetworkReply::QNetworkReply::ContentAccessDenied && iNetworkError != QNetworkReply::QNetworkReply::ContentNotFoundError )
1776 // don't stop on this error, only inform the user
1777 iMainWindow->notifyDialog("Network error", "There was a network error while fetching date information, the fetch was aborted");
1782 iUiDimmer->setProgress(-1);
1784 communicateStatusToUi(false, "Operation cancelled", "The operation was cancelled by user");
1790 iUiDimmer->setProgress(100);
1791 QApplication::processEvents();
1794 QString dbgstr = QString("sent %1 requests, received %2 replies with %3 errors").arg(iDateRequestsSent).arg(iDateRequestsReceived).arg(iDateRequestErrors);
1799 logToFile( QString("Finished fetching package dates") );
1801 if( fetchable.count()>0 || !dateCacheExists() ) {
1802 iUiDimmer->updateText("Writing date cache");
1803 QApplication::processEvents();
1808 iUiDimmer->updateText("Creating package view");
1809 QApplication::processEvents();
1810 iUiDimmer->setProgress(-1);
1813 communicateStatusToUi(true, "Operation finished", "Package dates fetched");
1814 iNeedDateRefresh = false;
1818 void AAptInterface::dateFetchNetworkReply(QNetworkReply* reply)
1820 iDateRequestsWaiting--;
1821 iDateRequestsReceived++;
1822 iNetworkError = reply->error();
1823 QDateTime dateModified = reply->header(QNetworkRequest::LastModifiedHeader).toDateTime();
1825 if( reply->error() == QNetworkReply::NoError && dateModified.isValid() )
1827 QString pkgname = reply->url().fragment();
1828 //qDebug() << pkgname;
1830 if( pkgname.isEmpty() )
1831 qDebug() << "warning: empty packagename in reply";
1833 Package* pkg = iPackagesAvailable.value(pkgname, 0);
1835 pkg->setDate( dateModified );
1837 qDebug() << "warning: unknown packagename in reply:" << pkgname;
1841 if( reply->error() != QNetworkReply::NoError ) {
1842 QString dbg = reply->url().fragment() + QString(": error %1: ").arg(reply->error()) + reply->errorString();
1845 iDateRequestErrors++;
1847 reply->deleteLater();
1850 void AAptInterface::writeDateCache()
1852 qDebug() << "writing date cache";
1854 QFile f(KDateCacheFile);
1855 if( f.open(QIODevice::WriteOnly | QIODevice::Text ) )
1857 QTextStream out(&f);
1858 QHashIterator<QString, Package*> i( iPackagesAvailable );
1859 while (i.hasNext() )
1862 if( i.value()->date().isValid() && i.value()->section().startsWith("user/") )
1863 out << i.value()->name() << " " << i.value()->version() << " " << i.value()->date().toString(Qt::ISODate) << "\n";
1867 qDebug() << "Warning: failed to write date cache";
1868 logToFile(QString("Failed to write date cache"));
1872 void AAptInterface::readDateCache()
1874 qDebug() << "reading date cache";
1876 QFile f(KDateCacheFile);
1877 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1879 while( !f.atEnd() ) {
1880 QString line = f.readLine().trimmed();
1881 QStringList parts = line.split(' ');
1882 if( parts.count()==3 ) {
1883 Package* pkg = iPackagesAvailable.value(parts.at(0),0);
1884 if( pkg && pkg->section().startsWith("user/") && pkg->version()==parts.at(1) )
1886 QDateTime dt = QDateTime::fromString( parts.at(2), Qt::ISODate);
1887 if( dt.isValid() ) {
1890 qDebug() << "Warning: Invalid date in date cache";
1891 logToFile(QString("Invalid date in date cache"));
1895 qDebug() << "Warning: error in date cache:" << line;
1896 logToFile(QString("Error in date cache"));
1901 qDebug() << "date cache does not exist";
1905 bool AAptInterface::dateCacheExists()
1907 QFileInfo f(KDateCacheFile);
1911 void AAptInterface::readPinnedPackages()
1913 QFile f(KAptPreferencesFile);
1917 bool warnAllPinned = false;
1918 if( f.open(QIODevice::ReadOnly | QIODevice::Text ) )
1920 qDebug() << "apt preferences exist: reading pinned packages";
1921 int pinned_packages = 0;
1924 QString line = f.readLine().trimmed();
1926 if( line=="Package: *" || line=="Package:*")
1927 warnAllPinned = true;
1929 if( line.startsWith("Package:") ) {
1931 QString pkg = line.mid(8).trimmed();
1932 Package* pkg_i = iPackagesInstalled.value(pkg,0);
1934 pkg_i->setPinned(true);
1936 Package* pkg_a = iPackagesAvailable.value(pkg,0);
1938 pkg_a->setPinned(true);
1943 qDebug() << "read" << pinned_packages << "pinned packages";
1946 if( warnAllPinned ) {
1947 iMainWindow->notifyDialog("Warning","You have pinned packages with '*' in apt preferences. It is strongly recommended to "
1948 "remove such settings as they can result in unexpected behavior of Faster Application Manager.");
1952 bool AAptInterface::loadInstallFiles(QStringList files_)