2017-03-21 22:20:24 +01:00
/*
KLayout Layout Viewer
Copyright ( C ) 2006 - 2017 Matthias Koefferlein
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# include "laySaltDownloadManager.h"
2017-03-27 15:46:01 +02:00
# include "laySalt.h"
# include "tlFileUtils.h"
# include "tlWebDAV.h"
# include "ui_SaltManagerInstallConfirmationDialog.h"
# include <QTreeWidgetItem>
2017-03-27 23:55:26 +02:00
# include <QMessageBox>
2017-03-21 22:20:24 +01:00
namespace lay
{
2017-03-27 15:46:01 +02:00
// ----------------------------------------------------------------------------------
class ConfirmationDialog
: public QDialog , private Ui : : SaltManagerInstallConfirmationDialog
{
public :
ConfirmationDialog ( QWidget * parent )
: QDialog ( parent )
{
Ui : : SaltManagerInstallConfirmationDialog : : setupUi ( this ) ;
}
void add_info ( const std : : string & name , bool update , const std : : string & version , const std : : string & url )
{
QTreeWidgetItem * item = new QTreeWidgetItem ( list ) ;
2017-03-27 23:55:26 +02:00
item - > setFlags ( item - > flags ( ) & ~ Qt : : ItemIsSelectable ) ;
2017-03-27 15:46:01 +02:00
item - > setText ( 0 , tl : : to_qstring ( name ) ) ;
item - > setText ( 1 , update ? tr ( " UPDATE " ) : tr ( " INSTALL " ) ) ;
item - > setText ( 2 , tl : : to_qstring ( version ) ) ;
item - > setText ( 3 , tl : : to_qstring ( url ) ) ;
2017-03-27 23:55:26 +02:00
for ( int column = 0 ; column < list - > colorCount ( ) ; + + column ) {
item - > setData ( column , Qt : : ForegroundRole , update ? Qt : : blue : Qt : : black ) ;
}
2017-03-27 15:46:01 +02:00
}
} ;
// ----------------------------------------------------------------------------------
2017-03-21 22:20:24 +01:00
SaltDownloadManager : : SaltDownloadManager ( )
{
// .. nothing yet ..
}
2017-03-27 15:46:01 +02:00
void
SaltDownloadManager : : register_download ( const std : : string & name , const std : : string & url , const std : : string & version )
{
m_registry . insert ( std : : make_pair ( name , Descriptor ( url , version ) ) ) ;
}
void
SaltDownloadManager : : compute_dependencies ( const lay : : Salt & salt , const lay : : Salt & salt_mine )
{
tl : : AbsoluteProgress progress ( tl : : to_string ( QObject : : tr ( " Computing package dependencies .. " ) ) ) ;
2017-03-27 23:55:26 +02:00
std : : map < std : : string , Descriptor > registry ;
// remove those registered entries which don't need to be updated
registry = m_registry ;
for ( std : : map < std : : string , Descriptor > : : const_iterator p = registry . begin ( ) ; p ! = registry . end ( ) ; + + p ) {
const SaltGrain * g = salt . grain_by_name ( p - > first ) ;
if ( g & & SaltGrain : : compare_versions ( p - > second . version , g - > version ( ) ) = = 0 & & p - > second . url = = g - > url ( ) ) {
m_registry . erase ( p - > first ) ;
}
}
// add further entries as derived from the dependencies
2017-03-27 15:46:01 +02:00
while ( needs_iteration ( ) ) {
fetch_missing ( salt_mine , progress ) ;
2017-03-27 23:55:26 +02:00
registry = m_registry ;
2017-03-27 15:46:01 +02:00
for ( std : : map < std : : string , Descriptor > : : const_iterator p = registry . begin ( ) ; p ! = registry . end ( ) ; + + p ) {
for ( std : : vector < SaltGrain : : Dependency > : : const_iterator d = p - > second . grain . dependencies ( ) . begin ( ) ; d ! = p - > second . grain . dependencies ( ) . end ( ) ; + + d ) {
std : : map < std : : string , Descriptor > : : iterator r = m_registry . find ( d - > name ) ;
if ( r ! = m_registry . end ( ) ) {
if ( SaltGrain : : compare_versions ( r - > second . version , d - > version ) < 0 ) {
// Grain is present, but too old -> update version and reload in the next iteration
r - > second . downloaded = false ;
r - > second . version = d - > version ;
r - > second . url = d - > url ;
r - > second . downloaded = false ;
}
} else {
const SaltGrain * g = salt . grain_by_name ( d - > name ) ;
if ( g ) {
// Grain is installed already, but too old -> register for update
if ( SaltGrain : : compare_versions ( g - > version ( ) , d - > version ) < 0 ) {
register_download ( d - > name , d - > url , d - > version ) ;
}
} else {
register_download ( d - > name , d - > url , d - > version ) ;
}
}
}
}
}
}
2017-03-21 22:20:24 +01:00
bool
2017-03-27 15:46:01 +02:00
SaltDownloadManager : : needs_iteration ( )
2017-03-21 22:20:24 +01:00
{
2017-03-27 15:46:01 +02:00
for ( std : : map < std : : string , Descriptor > : : const_iterator p = m_registry . begin ( ) ; p ! = m_registry . end ( ) ; + + p ) {
if ( ! p - > second . downloaded ) {
return true ;
}
}
2017-03-21 22:20:24 +01:00
return false ;
}
2017-03-27 15:46:01 +02:00
void
SaltDownloadManager : : fetch_missing ( const lay : : Salt & salt_mine , tl : : AbsoluteProgress & progress )
{
for ( std : : map < std : : string , Descriptor > : : iterator p = m_registry . begin ( ) ; p ! = m_registry . end ( ) ; + + p ) {
if ( ! p - > second . downloaded ) {
+ + progress ;
// If no URL is given, utilize the salt mine to fetch it
if ( p - > second . url . empty ( ) ) {
const lay : : SaltGrain * g = salt_mine . grain_by_name ( p - > first ) ;
if ( SaltGrain : : compare_versions ( g - > version ( ) , p - > second . version ) < 0 ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " Package '%1': package in repository is too old (%2) to satisfy requirements (%3) " ) . arg ( tl : : to_qstring ( p - > first ) ) . arg ( tl : : to_qstring ( g - > version ( ) ) ) . arg ( tl : : to_qstring ( p - > second . version ) ) ) ) ;
}
p - > second . version = g - > version ( ) ;
p - > second . url = g - > url ( ) ;
}
2017-03-27 23:55:26 +02:00
try {
p - > second . grain = SaltGrain : : from_url ( p - > second . url ) ;
} catch ( tl : : Exception & ex ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " Error fetching spec file for package '%1': %2 " ) . arg ( tl : : to_qstring ( p - > first ) ) . arg ( tl : : to_qstring ( ex . msg ( ) ) ) ) ) ;
}
2017-03-27 15:46:01 +02:00
p - > second . downloaded = true ;
}
}
}
bool
SaltDownloadManager : : show_confirmation_dialog ( QWidget * parent , const lay : : Salt & salt )
{
2017-03-27 23:55:26 +02:00
// Stop with a warning if there is nothing to do
if ( m_registry . empty ( ) ) {
QMessageBox : : warning ( parent , tr ( " Nothing to do " ) , tr ( " No packages need update or are marked for installation " ) ) ;
return false ;
}
2017-03-27 15:46:01 +02:00
lay : : ConfirmationDialog dialog ( parent ) ;
// First the packages to update
for ( std : : map < std : : string , Descriptor > : : const_iterator p = m_registry . begin ( ) ; p ! = m_registry . end ( ) ; + + p ) {
const lay : : SaltGrain * g = salt . grain_by_name ( p - > first ) ;
if ( g ) {
2017-03-27 23:55:26 +02:00
// \342\206\222 is UTF-8 "right arrow"
dialog . add_info ( p - > first , true , g - > version ( ) + " \342 \206 \222 " + p - > second . version , p - > second . url ) ;
2017-03-27 15:46:01 +02:00
}
}
// Then the packages to install
for ( std : : map < std : : string , Descriptor > : : const_iterator p = m_registry . begin ( ) ; p ! = m_registry . end ( ) ; + + p ) {
const lay : : SaltGrain * g = salt . grain_by_name ( p - > first ) ;
if ( ! g ) {
dialog . add_info ( p - > first , false , p - > second . version , p - > second . url ) ;
}
}
return dialog . exec ( ) ;
}
bool
SaltDownloadManager : : execute ( lay : : Salt & salt )
{
bool result = true ;
tl : : RelativeProgress progress ( tl : : to_string ( QObject : : tr ( " Downloading packages " ) ) , m_registry . size ( ) , 1 ) ;
for ( std : : map < std : : string , Descriptor > : : const_iterator p = m_registry . begin ( ) ; p ! = m_registry . end ( ) ; + + p ) {
lay : : SaltGrain target ;
target . set_name ( p - > first ) ;
lay : : SaltGrain * g = salt . grain_by_name ( p - > first ) ;
if ( g ) {
target . set_path ( g - > path ( ) ) ;
}
if ( ! salt . create_grain ( p - > second . grain , target ) ) {
result = false ;
}
+ + progress ;
}
return result ;
}
2017-03-21 22:20:24 +01:00
}