227 changes: 166 additions & 61 deletions src/app/pluginmanager/qgspluginmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ const QString seenPluginGroup = "/Qgis/plugin-seen";
QgsPluginManager::QgsPluginManager( QWidget * parent, Qt::WFlags fl )
: QgsOptionsDialogBase( "PluginManager", parent, fl )
{
// initialize pointer
mPythonUtils = NULL;

setupUi( this );

// QgsOptionsDialogBase handles saving/restoring of geometry, splitter and current tab states,
Expand All @@ -72,63 +75,92 @@ QgsPluginManager::QgsPluginManager( QWidget * parent, Qt::WFlags fl )
mModelProxy = new QgsPluginSortFilterProxyModel( this );
mModelProxy->setSourceModel( mModelPlugins );
mModelProxy->setSortCaseSensitivity( Qt::CaseInsensitive );
mModelProxy->setSortRole( Qt::DisplayRole );
mModelProxy->setDynamicSortFilter( true );
vwPlugins->setModel( mModelProxy );
vwPlugins->setFocus();

// context menu
// Preset widgets
QString wellcomeMsg = tr( "To enable or disable plugin, click its checkbox or doubleclick its name..." );
tbDetails->setHtml( wellcomeMsg );
leFilter->setFocus( Qt::MouseFocusReason );
rbFilterNames->setChecked( true );

// Don't restore the last used tab from QSettings
mOptionsListWidget->setCurrentRow( 0 );

// Connect other signals
connect( mOptionsListWidget, SIGNAL( currentRowChanged( int ) ), this, SLOT( setCurrentTab( int ) ) );
connect( vwPlugins->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( currentPluginChanged( const QModelIndex & ) ) );
connect( mModelPlugins, SIGNAL( itemChanged( QStandardItem * ) ), this, SLOT( pluginItemChanged( QStandardItem * ) ) );

// Force setting the status filter (if the active tab was 0, the setCurrentRow( 0 ) above doesn't take any action)
setCurrentTab( 0 );

// Hide widgets only suitable with Python support enabled (they will be uncovered back in setPythonUtils)
rbFilterTags->hide();
rbFilterAuthors->hide();
buttonUpgradeAll->hide();
buttonInstall->hide();
buttonUninstall->hide();
mOptionsListWidget->item( 5 )->setHidden( true );
}



QgsPluginManager::~QgsPluginManager()
{
delete mModelProxy;
delete mModelPlugins;
}



void QgsPluginManager::setPythonUtils( QgsPythonUtils* pythonUtils )
{
mPythonUtils = pythonUtils;

// Now enable Python support:
// Show and preset widgets only suitable when Python support active
rbFilterTags->show();
rbFilterAuthors->show();
buttonUpgradeAll->show();
buttonInstall->show();
buttonUninstall->show();
mOptionsListWidget->item( 5 )->setHidden( false );
buttonRefreshRepos->setEnabled( false );
buttonEditRep->setEnabled( false );
buttonDeleteRep->setEnabled( false );

// Add context menu to the plugins list view
QAction* actionSortByName = new QAction( tr( "sort by name" ), vwPlugins );
QAction* actionSortByDownloads = new QAction( tr( "sort by downloads" ), vwPlugins );
QAction* actionSortByVote = new QAction( tr( "sort by vote" ), vwPlugins );
QAction* actionSortByStatus = new QAction( tr( "sort by status" ), vwPlugins );
QAction* actionSortByRepository = new QAction( tr( "sort by repository" ), vwPlugins );
actionSortByName->setCheckable( true );
actionSortByDownloads->setCheckable( true );
actionSortByVote->setCheckable( true );
actionSortByStatus->setCheckable( true );
actionSortByRepository->setCheckable( true );
QActionGroup * group = new QActionGroup( vwPlugins );
actionSortByName->setActionGroup( group );
actionSortByDownloads->setActionGroup( group );
actionSortByVote->setActionGroup( group );
actionSortByStatus->setActionGroup( group );
actionSortByRepository->setActionGroup( group );
actionSortByName->setChecked( true );
vwPlugins->addAction( actionSortByName );
vwPlugins->addAction( actionSortByDownloads );
vwPlugins->addAction( actionSortByVote );
vwPlugins->addAction( actionSortByStatus );
vwPlugins->addAction( actionSortByRepository );
vwPlugins->setContextMenuPolicy( Qt::ActionsContextMenu );
connect( actionSortByName, SIGNAL( triggered( ) ), mModelProxy, SLOT( sortPluginsByName( ) ) );
connect( actionSortByDownloads, SIGNAL( triggered( ) ), mModelProxy, SLOT( sortPluginsByDownloads( ) ) );
connect( actionSortByVote, SIGNAL( triggered( ) ), mModelProxy, SLOT( sortPluginsByVote( ) ) );
connect( actionSortByStatus, SIGNAL( triggered( ) ), mModelProxy, SLOT( sortPluginsByStatus( ) ) );
connect( actionSortByRepository, SIGNAL( triggered( ) ), mModelProxy, SLOT( sortPluginsByRepository( ) ) );
mModelProxy->setSortRole( Qt::DisplayRole );

// Connect other signals
connect( mOptionsListWidget, SIGNAL( currentRowChanged( int ) ), this, SLOT( setCurrentTab( int ) ) );
connect( vwPlugins->selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), this, SLOT( currentPluginChanged( const QModelIndex & ) ) );
connect( mModelPlugins, SIGNAL( itemChanged( QStandardItem * ) ), this, SLOT( pluginItemChanged( QStandardItem * ) ) );

QString wellcomeMsg = tr( "To enable or disable plugin, click its checkbox or doubleclick its name..." );
tbDetails->setHtml( wellcomeMsg );
leFilter->setFocus( Qt::MouseFocusReason );
rbFilterNames->setChecked( true );
buttonRefreshRepos->setEnabled( false );
buttonEditRep->setEnabled( false );
buttonDeleteRep->setEnabled( false );

// Don't restore the last used tab from QSettings
mOptionsListWidget->setCurrentRow( 0 );

// Force setting the status filter (if the active tab was 0, the previous line doesn't take any action)
setCurrentTab( 0 );

// Initialize list of allowed checking intervals
checkingOnStartIntervals << 0 << 1 << 3 << 7 << 14 << 30 ;
mCheckingOnStartIntervals << 0 << 1 << 3 << 7 << 14 << 30 ;

// Initialize the "Setting" tab widgets
// Initialize the "Settings" tab widgets
QSettings settings;
if ( settings.value( settingsGroup + "/checkOnStart", false ).toBool() )
{
Expand All @@ -141,27 +173,12 @@ QgsPluginManager::QgsPluginManager( QWidget * parent, Qt::WFlags fl )
}

int interval = settings.value( settingsGroup + "/checkOnStartInterval", "" ).toInt( );
int indx = checkingOnStartIntervals.indexOf( interval ); // if none found, just use -1 index.
int indx = mCheckingOnStartIntervals.indexOf( interval ); // if none found, just use -1 index.
comboInterval->setCurrentIndex( indx );
}



QgsPluginManager::~QgsPluginManager()
{
delete mModelProxy;
delete mModelPlugins;
}



void QgsPluginManager::setPythonUtils( QgsPythonUtils* pythonUtils )
{
mPythonUtils = pythonUtils;
}



void QgsPluginManager::loadPlugin( QString id )
{
QMap<QString, QString>* plugin = pluginMetadata( id );
Expand Down Expand Up @@ -220,7 +237,7 @@ void QgsPluginManager::unloadPlugin( QString id )



void QgsPluginManager::getCppPluginDescriptions()
void QgsPluginManager::getCppPluginsMetadata()
{
QString sharedLibExtension;
#if defined(WIN32) || defined(__CYGWIN__)
Expand Down Expand Up @@ -371,6 +388,7 @@ void QgsPluginManager::getCppPluginDescriptions()
metadata["pythonic"] = "false";
metadata["installed"] = "true";
metadata["readonly"] = "true";
metadata["status"] = "orphan";
metadata["experimental"] = ( pExperimental ? pExperimental() : QString() );
mPlugins.insert( baseName, metadata );

Expand All @@ -381,6 +399,22 @@ void QgsPluginManager::getCppPluginDescriptions()



QStandardItem * QgsPluginManager::createSpacerItem( QString text, QString value )
{
QStandardItem * mySpacerltem = new QStandardItem( text );
mySpacerltem->setData( value, PLUGIN_STATUS_ROLE );
mySpacerltem->setData( "status", SPACER_ROLE );
mySpacerltem->setEnabled( false );
mySpacerltem->setEditable( false );
QFont font = mySpacerltem->font();
font.setBold( true );
mySpacerltem->setFont( font );
mySpacerltem->setTextAlignment( Qt::AlignHCenter );
return mySpacerltem;
}



void QgsPluginManager::reloadModelData()
{
mModelPlugins->clear();
Expand All @@ -389,7 +423,6 @@ void QgsPluginManager::reloadModelData()
it != mPlugins.end();
it++ )
{

if ( ! it->value( "id" ).isEmpty() )
{
QString baseName = it->value( "id" );
Expand Down Expand Up @@ -464,11 +497,22 @@ void QgsPluginManager::reloadModelData()
}
}

// Add spacers for sort by status
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
// TODO: implement better sort method instead of these dummy -Z statuses
mModelPlugins->appendRow( createSpacerItem( tr( "Reinstallable plugins", "category: plugins that are installed and available" ) , "installedZ" ) );
if ( hasUpgradeablePlugins() ) mModelPlugins->appendRow( createSpacerItem( tr( "Upgradeable plugins", "category: plugins that are installed and there is newer version available" ), "upgradeableZ") );
mModelPlugins->appendRow( createSpacerItem( tr( "Only locally available", "category: plugins that are only locally available" ), "orphanZ" ) );
if ( hasNewerPlugins() ) mModelPlugins->appendRow( createSpacerItem( tr( "Newer locally", "category: plugins installed and availabie; installed version is newer" ), "newerZ" ) );
}

updateTabTitle();

buttonUpgradeAll->setEnabled( hasUpgradeablePlugins() );

// Disable tabs that are empty because of no suitable plugins in the model.
mOptionsListWidget->item( 1 )->setHidden( ! hasAvailablePlugins() );
mOptionsListWidget->item( 2 )->setHidden( ! hasUpgradeablePlugins() );
mOptionsListWidget->item( 3 )->setHidden( ! hasNewPlugins() );
mOptionsListWidget->item( 4 )->setHidden( ! hasInvalidPlugins() );
Expand Down Expand Up @@ -525,11 +569,11 @@ void QgsPluginManager::showPluginDetails( QStandardItem * item )
QString errorMsg;
if ( metadata->value( "error" ) == "incompatible" )
{
errorMsg = QString( "<b>%1</b><br/><%2> %3" ).arg( tr( "This plugin is incompatible with this version of QGIS" ) ).arg( tr( "Compatible versions:" ) ).arg( metadata->value( "error_details" ) );
errorMsg = QString( "<b>%1</b><br/>%2" ).arg( tr( "This plugin is incompatible with this version of QGIS" ) ).arg( tr( "Plugin designed for QGIS %1", "compatible QGIS version(s)" ).arg( metadata->value( "error_details" ) ) );
}
else if ( metadata->value( "error" ) == "dependent" )
{
errorMsg = QString( "<b>%1</b>:<br/>%2" ).arg( tr( "This plugin requires a missing module" ) ).arg( metadata->value( "error_details" ) );
errorMsg = QString( "<b>%1:</b><br/>%2" ).arg( tr( "This plugin requires a missing module" ) ).arg( metadata->value( "error_details" ) );
}
else
{
Expand Down Expand Up @@ -665,22 +709,20 @@ void QgsPluginManager::showPluginDetails( QStandardItem * item )
{
buttonInstall->setText( tr( "Downgrade plugin" ) );
}
else if ( metadata->value( "status" ) == "installed" )
{
buttonInstall->setText( tr( "Reinstall plugin" ) );
}
else if ( metadata->value( "status" ) == "not installed" || metadata->value( "status" ) == "new" )
{
buttonInstall->setText( tr( "Install plugin" ) );
}
else
{
buttonInstall->setText( tr( "Install/upgrade plugin" ) );
// Default (will be grayed out if not available for reinstallation)
buttonInstall->setText( tr( "Reinstall plugin" ) );
}

// Enable/disable buttons
buttonInstall->setEnabled( metadata->value( "pythonic" ).toUpper() == "TRUE" && metadata->value( "status" ) != "orphan" );
buttonUninstall->setEnabled( metadata->value( "pythonic" ).toUpper() == "TRUE" && metadata->value( "status" ) != "readonly" && metadata->value( "status" ) != "not installed" && metadata->value( "status" ) != "new" );
buttonUninstall->setHidden( metadata->value( "status" ) == "not installed" || metadata->value( "status" ) == "new" );

// Store the id of the currently displayed plugin
mCurrentlyDisplayedPlugin = metadata->value( "id" );
Expand Down Expand Up @@ -743,6 +785,16 @@ void QgsPluginManager::clearRepositoryList()
//! Add repository to the repository listWidget
void QgsPluginManager::addToRepositoryList( QMap<QString, QString> repository )
{
// If the item is second on the tree, add a context menu
if ( buttonRefreshRepos->isEnabled() && treeRepositories->actions().count() < 1 )
{
QAction* actionEnableThisRepositoryOnly = new QAction( tr( "Enable selected repository only" ), treeRepositories );
actionEnableThisRepositoryOnly->setCheckable( true );
treeRepositories->addAction( actionEnableThisRepositoryOnly );
treeRepositories->setContextMenuPolicy( Qt::ActionsContextMenu );
connect( actionEnableThisRepositoryOnly, SIGNAL( toggled( bool ) ), this, SLOT( enableSelectedRepositoryOnly( bool ) ) );
}

QString key = repository.value( "name" );
if ( ! key.isEmpty() )
{
Expand Down Expand Up @@ -795,14 +847,16 @@ void QgsPluginManager::addToRepositoryList( QMap<QString, QString> repository )
// SLOTS ///////////////////////////////////////////////////////////////////



// "Close" button clicked
void QgsPluginManager::reject()
{
QSettings settings;
settings.setValue( settingsGroup + "/checkOnStart", QVariant( ckbCheckUpdates->isChecked() ) );
settings.setValue( settingsGroup + "/checkOnStartInterval", QVariant( checkingOnStartIntervals.value( comboInterval->currentIndex() ) ) );
QgsPythonRunner::run( "pyplugin_installer.instance().onManagerClose()" );
if ( mPythonUtils && mPythonUtils->isEnabled() )
{
QSettings settings;
settings.setValue( settingsGroup + "/checkOnStart", QVariant( ckbCheckUpdates->isChecked() ) );
settings.setValue( settingsGroup + "/checkOnStartInterval", QVariant( mCheckingOnStartIntervals.value( comboInterval->currentIndex() ) ) );
QgsPythonRunner::run( "pyplugin_installer.instance().onManagerClose()" );
}
done( 1 );
}

Expand All @@ -824,8 +878,8 @@ void QgsPluginManager::setCurrentTab( int idx )
switch ( idx )
{
case 0:
// installed
acceptedStatuses << "installed" << "orphan" << "newer" << "upgradeable" << "";
// installed (statuses ends with Z are for spacers to always sort properly)
acceptedStatuses << "installed" << "orphan" << "newer" << "upgradeable" << "installedZ" << "upgradeableZ" << "orphanZ" << "newerZZ" << "" ;
break;
case 1:
// not installed (get more)
Expand Down Expand Up @@ -996,6 +1050,26 @@ void QgsPluginManager::on_treeRepositories_doubleClicked( QModelIndex )



void QgsPluginManager::enableSelectedRepositoryOnly( bool checked )
{
if ( ! checked ) {
QgsDebugMsg( "Enabling all repositories back");
QgsPythonRunner::run( QString( "pyplugin_installer.instance().enableThisRepositoryOnly()" ) );
return;
}

QTreeWidgetItem * current = treeRepositories->currentItem();
if ( current )
{
QString key = current->text( 1 );
key = key.replace( "\'", "\\\'" ).replace( "\"", "\\\"" );
QgsDebugMsg( "Disabling all repositories but selected: " + key );
QgsPythonRunner::run( QString( "pyplugin_installer.instance().enableThisRepositoryOnly('%1')" ).arg( key ) );
}
}



void QgsPluginManager::on_buttonRefreshRepos_clicked( )
{
QgsDebugMsg( "Refreshing repositories..." );
Expand Down Expand Up @@ -1053,7 +1127,6 @@ void QgsPluginManager::on_ckbExperimental_toggled( bool state )
// PRIVATE METHODS ///////////////////////////////////////////////////////////////////



bool QgsPluginManager::isPluginLoaded( QString key )
{
QMap<QString, QString>* plugin = pluginMetadata( key );
Expand Down Expand Up @@ -1083,6 +1156,21 @@ bool QgsPluginManager::isPluginLoaded( QString key )
}


bool QgsPluginManager::hasAvailablePlugins( )
{
for ( QMap<QString, QMap<QString, QString> >::iterator it = mPlugins.begin();
it != mPlugins.end();
it++ )
{
if ( it->value( "status" ) == "not installed" || it->value( "status" ) == "new" )
{
return true;
}
}

return false;
}


bool QgsPluginManager::hasUpgradeablePlugins( )
{
Expand Down Expand Up @@ -1118,6 +1206,23 @@ bool QgsPluginManager::hasNewPlugins( )



bool QgsPluginManager::hasNewerPlugins( )
{
for ( QMap<QString, QMap<QString, QString> >::iterator it = mPlugins.begin();
it != mPlugins.end();
it++ )
{
if ( it->value( "status" ) == "newer" )
{
return true;
}
}

return false;
}



bool QgsPluginManager::hasInvalidPlugins( )
{
for ( QMap<QString, QMap<QString, QString> >::iterator it = mPlugins.begin();
Expand Down
24 changes: 18 additions & 6 deletions src/app/pluginmanager/qgspluginmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class QgsPluginManager : public QgsOptionsDialogBase, private Ui::QgsPluginManag
//! Destructor
~QgsPluginManager();

//! Save pointer to python utils
//! Save pointer to python utils and enable Python support
void setPythonUtils( QgsPythonUtils* pythonUtils );

//! Load selected plugin
Expand All @@ -54,7 +54,10 @@ class QgsPluginManager : public QgsOptionsDialogBase, private Ui::QgsPluginManag
void unloadPlugin( QString id );

//! Get metadata of C++ plugins
void getCppPluginDescriptions();
void getCppPluginsMetadata();

//! Create new spacer item for sorting by status in the plugin list view
QStandardItem * createSpacerItem( QString text, QString value );

//! Repopulate the plugin list model
void reloadModelData();
Expand Down Expand Up @@ -153,17 +156,26 @@ class QgsPluginManager : public QgsOptionsDialogBase, private Ui::QgsPluginManag
//! Reimplement QgsOptionsDialogBase method to prevent modifying the tab list by signals from the stacked widget
void optionsStackedWidget_CurrentChanged( int indx ) { Q_UNUSED( indx ) }

//! Enable selected repository only
void enableSelectedRepositoryOnly( bool checked );

private:
//! Return true if given plugin is currently present in QgsPluginRegistry
bool isPluginLoaded( QString key );

//! Return true if there are upgradeable plugins in the registry
//! Return true if there are plugins available for download in the metadata registry
bool hasAvailablePlugins( );

//! Return true if there are upgradeable plugins in metadata the registry
bool hasUpgradeablePlugins( );

//! Return true if there are new plugins in the registry
//! Return true if there are new plugins in the metadata registry
bool hasNewPlugins( );

//! Return true if there are invalid plugins in the registry
//! Return true if there are plugins in the metadata registry that are newer installed than available
bool hasNewerPlugins( );

//! Return true if there are invalid plugins in the metadata registry
bool hasInvalidPlugins( );

QStandardItemModel *mModelPlugins;
Expand All @@ -176,7 +188,7 @@ class QgsPluginManager : public QgsOptionsDialogBase, private Ui::QgsPluginManag

QString mCurrentlyDisplayedPlugin;

QList<int> checkingOnStartIntervals;
QList<int> mCheckingOnStartIntervals;
};

#endif
34 changes: 24 additions & 10 deletions src/app/pluginmanager/qgspluginsortfilterproxymodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
***************************************************************************/

#include "qgspluginsortfilterproxymodel.h"
#include "qgslogger.h"



QgsPluginSortFilterProxyModel::QgsPluginSortFilterProxyModel( QObject *parent ) : QSortFilterProxyModel( parent )
{
Expand All @@ -27,6 +28,13 @@ bool QgsPluginSortFilterProxyModel::filterAcceptsRow( int sourceRow, const QMode
{
QModelIndex inx = sourceModel()->index( sourceRow, 0, sourceParent );

if ( ! sourceModel()->data( inx, SPACER_ROLE ).toString().isEmpty() )
{
// it's a status spacer.
// TODO: the condition below is only suitable for status spacers
return ( filterByStatus( inx ) && mAcceptedStatuses.count()>1 && sourceModel()->data( inx, SPACER_ROLE ).toString() == mAcceptedSpacers );
}

return ( filterByStatus( inx ) && sourceModel()->data( inx, filterRole() ).toString().contains( filterRegExp() ) );
}

Expand All @@ -40,6 +48,14 @@ void QgsPluginSortFilterProxyModel::setAcceptedStatuses( QStringList statuses )



void QgsPluginSortFilterProxyModel::setAcceptedSpacers( QString spacers )
{
mAcceptedSpacers = spacers;
invalidateFilter();
}



bool QgsPluginSortFilterProxyModel::filterByStatus( QModelIndex &index ) const
{
if ( mAcceptedStatuses.contains( "invalid" )
Expand All @@ -49,9 +65,11 @@ bool QgsPluginSortFilterProxyModel::filterByStatus( QModelIndex &index ) const
return false;
}

QString status = sourceModel()->data( index, PLUGIN_STATUS_ROLE ).toString();
if ( status.endsWith( "Z" ) ) status.chop( 1 );
if ( ! mAcceptedStatuses.isEmpty()
&& ! mAcceptedStatuses.contains( "invalid" )
&& ! mAcceptedStatuses.contains( sourceModel()->data( index, PLUGIN_STATUS_ROLE ).toString() ) )
&& ! mAcceptedStatuses.contains( status ) )
{
// Don't accept if the status doesn't match
return false;
Expand Down Expand Up @@ -81,6 +99,7 @@ int QgsPluginSortFilterProxyModel::countWithCurrentStatus( )

void QgsPluginSortFilterProxyModel::sortPluginsByName( )
{
setAcceptedSpacers();
sort( 0, Qt::AscendingOrder );
setSortRole( Qt::DisplayRole );
}
Expand All @@ -89,6 +108,7 @@ void QgsPluginSortFilterProxyModel::sortPluginsByName( )

void QgsPluginSortFilterProxyModel::sortPluginsByDownloads( )
{
setAcceptedSpacers();
sort( 0, Qt::DescendingOrder );
setSortRole( PLUGIN_DOWNLOADS_ROLE );
}
Expand All @@ -97,6 +117,7 @@ void QgsPluginSortFilterProxyModel::sortPluginsByDownloads( )

void QgsPluginSortFilterProxyModel::sortPluginsByVote( )
{
setAcceptedSpacers();
sort( 0, Qt::DescendingOrder );
setSortRole( PLUGIN_VOTE_ROLE );
}
Expand All @@ -105,14 +126,7 @@ void QgsPluginSortFilterProxyModel::sortPluginsByVote( )

void QgsPluginSortFilterProxyModel::sortPluginsByStatus( )
{
setAcceptedSpacers( "status" );
sort( 0, Qt::DescendingOrder );
setSortRole( PLUGIN_STATUS_ROLE );
}



void QgsPluginSortFilterProxyModel::sortPluginsByRepository( )
{
sort( 0, Qt::DescendingOrder );
setSortRole( PLUGIN_REPOSITORY_ROLE );
}
8 changes: 7 additions & 1 deletion src/app/pluginmanager/qgspluginsortfilterproxymodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <QSortFilterProxyModel>
#include <QStringList>
#include <QString>

const int PLUGIN_BASE_NAME_ROLE = Qt::UserRole + 1;
const int PLUGIN_DESCRIPTION_ROLE = Qt::UserRole + 2; // for filtering
Expand All @@ -29,6 +30,8 @@ const int PLUGIN_STATUS_ROLE = Qt::UserRole + 6; // for filtering and sort
const int PLUGIN_DOWNLOADS_ROLE = Qt::UserRole + 7; // for sorting
const int PLUGIN_VOTE_ROLE = Qt::UserRole + 8; // for sorting
const int PLUGIN_REPOSITORY_ROLE = Qt::UserRole + 9; // for sorting
const int SPACER_ROLE = Qt::UserRole + 20; // for sorting



/*!
Expand All @@ -44,6 +47,9 @@ class QgsPluginSortFilterProxyModel : public QSortFilterProxyModel
//! (Re)configire the status filter
void setAcceptedStatuses( QStringList statuses );

//! (Re)configire the spacer filter
void setAcceptedSpacers( QString spacers = "" );

//! Return number of item with status filter matching (no other filters are considered)
int countWithCurrentStatus( );

Expand All @@ -52,7 +58,6 @@ class QgsPluginSortFilterProxyModel : public QSortFilterProxyModel
void sortPluginsByDownloads( );
void sortPluginsByVote( );
void sortPluginsByStatus( );
void sortPluginsByRepository( );

protected:
//! Filter by status: this method is used in both filterAcceptsRow and countWithCurrentStatus.
Expand All @@ -63,6 +68,7 @@ class QgsPluginSortFilterProxyModel : public QSortFilterProxyModel

private:
QStringList mAcceptedStatuses;
QString mAcceptedSpacers;
};

#endif
4 changes: 2 additions & 2 deletions src/app/qgisapp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,11 +629,11 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, QWidget * parent,

if ( mPythonUtils && mPythonUtils->isEnabled() )
{
// pass the python utils to the plugin manager
mPluginManager -> setPythonUtils( mPythonUtils );
// initialize the plugin installer to start fetching repositories in background
QgsPythonRunner::run( "import pyplugin_installer" );
QgsPythonRunner::run( "pyplugin_installer.initPluginInstaller()" );
// enable Python in the Plugin Manager and pass the PythonUtils to it
mPluginManager -> setPythonUtils( mPythonUtils );
}

mSplash->showMessage( tr( "Initializing file filters" ), Qt::AlignHCenter | Qt::AlignBottom );
Expand Down
20 changes: 13 additions & 7 deletions src/ui/qgspluginmanagerbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -470,28 +470,34 @@ padding: 0px</string>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buttonInstall">
<widget class="QPushButton" name="buttonUninstall">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Install, reinstall or upgrade the selected plugin</string>
<string>Uninstall the selected plugin</string>
</property>
<property name="text">
<string>Install/upgrade plugin</string>
<string>Uninstall plugin</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonUninstall">
<widget class="QPushButton" name="buttonInstall">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>180</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Uninstall the selected plugin</string>
<string>Install, reinstall or upgrade the selected plugin</string>
</property>
<property name="text">
<string>Uninstall plugin</string>
<string>Reinstall plugin</string>
</property>
</widget>
</item>
Expand Down Expand Up @@ -897,8 +903,8 @@ p, li { white-space: pre-wrap; }
<tabstop>vwPlugins</tabstop>
<tabstop>tbDetails</tabstop>
<tabstop>buttonUpgradeAll</tabstop>
<tabstop>buttonInstall</tabstop>
<tabstop>buttonUninstall</tabstop>
<tabstop>buttonInstall</tabstop>
<tabstop>ckbCheckUpdates</tabstop>
<tabstop>comboInterval</tabstop>
<tabstop>ckbExperimental</tabstop>
Expand Down