diff --git a/python/pyplugin_installer/installer.py b/python/pyplugin_installer/installer.py index 42c18aab822..590c519f90e 100644 --- a/python/pyplugin_installer/installer.py +++ b/python/pyplugin_installer/installer.py @@ -143,12 +143,12 @@ class QgsPluginInstaller(QObject): for key in plugins.all(): if plugins.all()[key]["status"] == "new": status = self.tr("There is a new plugin available") - tabIndex = 3 # tab 3 contains new plugins + tabIndex = 4 # PLUGMAN_TAB_NEW # then check for updates (and eventually overwrite status) for key in plugins.all(): if plugins.all()[key]["status"] == "upgradeable": status = self.tr("There is a plugin update available") - tabIndex = 2 # tab 2 contains upgradeable plugins + tabIndex = 3 # PLUGMAN_TAB_UPGRADEABLE # finally set the notify label if status: self.statusLabel.setText(u' %s ' % (tabIndex,status) ) diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index a335f482df5..870775ca363 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -152,6 +152,7 @@ SET(QGIS_APP_SRCS pluginmanager/qgspluginmanager_texts.cpp pluginmanager/qgsapppluginmanagerinterface.cpp pluginmanager/qgspluginsortfilterproxymodel.cpp + pluginmanager/qgspluginitemdelegate.cpp qgsnewspatialitelayerdialog.cpp ) @@ -286,6 +287,7 @@ SET (QGIS_APP_MOC_HDRS pluginmanager/qgspluginmanager.h pluginmanager/qgsapppluginmanagerinterface.h pluginmanager/qgspluginsortfilterproxymodel.h + pluginmanager/qgspluginitemdelegate.h qgsnewspatialitelayerdialog.h ) diff --git a/src/app/pluginmanager/qgspluginitemdelegate.cpp b/src/app/pluginmanager/qgspluginitemdelegate.cpp new file mode 100644 index 00000000000..bcc47d9b4ab --- /dev/null +++ b/src/app/pluginmanager/qgspluginitemdelegate.cpp @@ -0,0 +1,102 @@ +/*************************************************************************** + qgspluginitemdelegate.cpp - a QItemDelegate subclass for plugin manager + ------------------- + begin : Fri Sep 13 2013, Brighton HF + copyright : (C) 2013 Borys Jurgiel + email : info@borysjurgiel.pl + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "qgspluginitemdelegate.h" +#include +#include +#include +#include +#include +#include "qgspluginsortfilterproxymodel.h" + + +QgsPluginItemDelegate::QgsPluginItemDelegate( QObject * parent ) : QStyledItemDelegate( parent ) {} + + +QSize QgsPluginItemDelegate::sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const +{ + Q_UNUSED( option ); + Q_UNUSED( index ); + return QSize( 20, 20 ); +} + + +void QgsPluginItemDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const +{ + painter->save(); + painter->setRenderHint( QPainter::SmoothPixmapTransform ); + QStyle *style = QApplication::style(); + + // Draw the background + style->drawPrimitive( QStyle::PE_PanelItemViewItem, &option, painter, NULL ); + + // Draw the checkbox + if ( index.flags() & Qt::ItemIsUserCheckable ) + { + QStyleOptionButton checkBoxStyle; + checkBoxStyle.rect = option.rect; + if ( index.data( Qt::CheckStateRole ).toBool() ) + { + checkBoxStyle.state = QStyle::State_On|QStyle::State_Enabled; + } + else + { + checkBoxStyle.state = QStyle::State_Off|QStyle::State_Enabled; + } + style->drawControl( QStyle::CE_CheckBox, &checkBoxStyle, painter ); + } + + // Draw the icon + QPixmap iconPixmap = index.data( Qt::DecorationRole ).value(); + + if ( !iconPixmap.isNull() ) + { + int iconSize = option.rect.height(); + painter->drawPixmap( option.rect.left() + 24 , option.rect.top(), iconSize, iconSize, iconPixmap ); + } + + // Draw the text + if ( option.state & QStyle::State_Selected ) + { + painter->setPen( option.palette.highlightedText().color() ); + } + else + { + painter->setPen( option.palette.text().color() ); + } + + if ( ! index.data( PLUGIN_ERROR_ROLE ).toString().isEmpty() ) + { + painter->setPen( Qt::red ); + } + + if ( ! index.data( PLUGIN_ERROR_ROLE ).toString().isEmpty() + || index.data( PLUGIN_STATUS_ROLE ).toString() == QString( "upgradeable" ) + || index.data( PLUGIN_STATUS_ROLE ).toString() == QString( "new" ) ) + { + QFont font = painter->font(); + font.setBold( true ); + painter->setFont( font ); + } + + painter->drawText( option.rect.left() + 48 , option.rect.bottom() - 3 , index.data( Qt::DisplayRole ).toString() ); + + painter->restore(); +} + + + diff --git a/src/app/pluginmanager/qgspluginitemdelegate.h b/src/app/pluginmanager/qgspluginitemdelegate.h new file mode 100644 index 00000000000..bdd8ef55c1d --- /dev/null +++ b/src/app/pluginmanager/qgspluginitemdelegate.h @@ -0,0 +1,34 @@ +/*************************************************************************** + qgspluginitemdelegate.h - a QItemDelegate subclass for plugin manager + ------------------- + begin : Fri Sep 13 2013, Brighton HF + copyright : (C) 2013 Borys Jurgiel + email : info@borysjurgiel.pl + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef QGSPLUGINITEMDELEGATE_H +#define QGSPLUGINITEMDELEGATE_H + +#include + +/** + * A custom model/view delegate that can eithe display checkbox or empty space for proprer text alignment + */ +class QgsPluginItemDelegate : public QStyledItemDelegate +{ + Q_OBJECT + public: + QgsPluginItemDelegate( QObject * parent = 0 ); + QSize sizeHint( const QStyleOptionViewItem & theOption, const QModelIndex & theIndex ) const; + void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const; +}; + +#endif //QGSPLUGINITEMDELEGATE_H diff --git a/src/app/pluginmanager/qgspluginmanager.cpp b/src/app/pluginmanager/qgspluginmanager.cpp index f625450d8a5..60ab24ee3f3 100644 --- a/src/app/pluginmanager/qgspluginmanager.cpp +++ b/src/app/pluginmanager/qgspluginmanager.cpp @@ -39,6 +39,7 @@ #include "qgspluginmanager.h" #include "qgisplugin.h" #include "qgslogger.h" +#include "qgspluginitemdelegate.h" // Do we need this? // #define TESTLIB @@ -87,6 +88,7 @@ QgsPluginManager::QgsPluginManager( QWidget * parent, bool pluginsAreEnabled, Qt mModelProxy->setDynamicSortFilter( true ); mModelProxy->sort( 0, Qt::AscendingOrder ); vwPlugins->setModel( mModelProxy ); + vwPlugins->setItemDelegate( new QgsPluginItemDelegate( vwPlugins ) ); vwPlugins->setFocus(); // Preset widgets @@ -493,29 +495,15 @@ void QgsPluginManager::reloadModelData() if ( QFileInfo( iconPath ).isFile() ) { - mypDetailItem->setIcon( QPixmap( iconPath ) ); + mypDetailItem->setData( QPixmap( iconPath ), Qt::DecorationRole ); } else { - mypDetailItem->setIcon( QPixmap( QgsApplication::defaultThemePath() + "/plugin.png" ) ); + mypDetailItem->setData( QPixmap( QgsApplication::defaultThemePath() + "/plugin.png" ), Qt::DecorationRole ); } mypDetailItem->setEditable( false ); - // set item display style - if ( ! it->value( "error" ).isEmpty() ) - { - QBrush brush = mypDetailItem->foreground(); - brush.setColor( Qt::red ); - mypDetailItem->setForeground( brush ); - } - if ( ! it->value( "error" ).isEmpty() || it->value( "status" ) == "upgradeable" || it->value( "status" ) == "new" ) - { - QFont font = mypDetailItem->font(); - font.setBold( true ); - mypDetailItem->setFont( font ); - } - // Set checkable if the plugin is installed and not disabled due to incompatibility. // Broken plugins are checkable to to allow disabling them mypDetailItem->setCheckable( it->value( "installed" ) == "true" && it->value( "error" ) != "incompatible" ); @@ -552,6 +540,7 @@ void QgsPluginManager::reloadModelData() if ( hasReinstallablePlugins() ) mModelPlugins->appendRow( createSpacerItem( tr( "Reinstallable", "category: plugins that are installed and available" ) , "installedZ" ) ); if ( hasUpgradeablePlugins() ) mModelPlugins->appendRow( createSpacerItem( tr( "Upgradeable", "category: plugins that are installed and there is a newer version available" ), "upgradeableZ" ) ); if ( hasNewerPlugins() ) mModelPlugins->appendRow( createSpacerItem( tr( "Downgradeable", "category: plugins that are installed and there is an OLDER version available" ), "newerZ" ) ); + if ( hasAvailablePlugins() ) mModelPlugins->appendRow( createSpacerItem( tr( "Installable", "category: plugins that are available for installation" ), "not installedZ" ) ); } updateTabTitle(); @@ -559,10 +548,10 @@ void QgsPluginManager::reloadModelData() 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() ); + mOptionsListWidget->item( PLUGMAN_TAB_NOT_INSTALLED )->setHidden( ! hasAvailablePlugins() ); + mOptionsListWidget->item( PLUGMAN_TAB_UPGRADEABLE )->setHidden( ! hasUpgradeablePlugins() ); + mOptionsListWidget->item( PLUGMAN_TAB_NEW )->setHidden( ! hasNewPlugins() ); + mOptionsListWidget->item( PLUGMAN_TAB_INVALID )->setHidden( ! hasInvalidPlugins() ); } @@ -973,27 +962,32 @@ void QgsPluginManager::setCurrentTab( int idx ) QString tabTitle; switch ( idx ) { - case 0: + case PLUGMAN_TAB_ALL: + // all (statuses ends with Z are for spacers to always sort properly) + acceptedStatuses << "installed" << "not installed" << "orphan" << "newer" << "upgradeable" << "not installedZ" << "installedZ" << "upgradeableZ" << "orphanZ" << "newerZZ" << "" ; + tabTitle = "all_plugins"; + break; + case PLUGMAN_TAB_INSTALLED: // installed (statuses ends with Z are for spacers to always sort properly) acceptedStatuses << "installed" << "orphan" << "newer" << "upgradeable" << "installedZ" << "upgradeableZ" << "orphanZ" << "newerZZ" << "" ; tabTitle = "installed_plugins"; break; - case 1: + case PLUGMAN_TAB_NOT_INSTALLED: // not installed (get more) acceptedStatuses << "not installed" << "new" ; - tabTitle = "get_more_plugins"; + tabTitle = "not_installed_plugins"; break; - case 2: + case PLUGMAN_TAB_UPGRADEABLE: // upgradeable acceptedStatuses << "upgradeable" ; tabTitle = "upgradeable_plugins"; break; - case 3: + case PLUGMAN_TAB_NEW: // new acceptedStatuses << "new" ; tabTitle = "new_plugins"; break; - case 4: + case PLUGMAN_TAB_INVALID: // invalid acceptedStatuses << "invalid" ; tabTitle = "invalid_plugins"; diff --git a/src/app/pluginmanager/qgspluginmanager.h b/src/app/pluginmanager/qgspluginmanager.h index 065f7c2db61..b339cc736af 100644 --- a/src/app/pluginmanager/qgspluginmanager.h +++ b/src/app/pluginmanager/qgspluginmanager.h @@ -30,6 +30,13 @@ #include "qgspythonutils.h" #include "qgspluginsortfilterproxymodel.h" +const int PLUGMAN_TAB_ALL = 0; +const int PLUGMAN_TAB_INSTALLED = 1; +const int PLUGMAN_TAB_NOT_INSTALLED = 2; +const int PLUGMAN_TAB_UPGRADEABLE = 3; +const int PLUGMAN_TAB_NEW = 4; +const int PLUGMAN_TAB_INVALID = 5; + /*! * \brief Plugin manager for browsing, (un)installing and (un)loading plugins @author Gary Sherman diff --git a/src/app/pluginmanager/qgspluginmanager_texts.cpp b/src/app/pluginmanager/qgspluginmanager_texts.cpp index bf495ea55d7..f20811fa243 100644 --- a/src/app/pluginmanager/qgspluginmanager_texts.cpp +++ b/src/app/pluginmanager/qgspluginmanager_texts.cpp @@ -8,22 +8,39 @@ void QgsPluginManager::initTabDescriptions() if ( !mTabDescriptions.isEmpty() ) return; - mTabDescriptions.insert( "installed_plugins", tr( "

Installed Plugins

\ + mTabDescriptions.insert( "all_plugins", tr( "

All Plugins

\ +\

\ -On the left you see the list of installed plugins on your system. Both python and cpp \ -plugins are listed. Some plugins come with your QGIS installation while most of\ - them are made available via the plugin repositories.\ +On the left you see the list of all plugins available for your QGIS, both installed and available for download. \ +Some plugins come with your QGIS installation while most of them are made available via the plugin repositories.\

\ \

\ You can temporarily enable or disable a plugin.\ -To enable or disable a plugin,\ - click its checkbox or doubleclick its name...\ + To enable or disable a plugin, click its checkbox or doubleclick its name...\

\ \

\ -Plugins showing in red are not loaded because there is a problem. Consult the \ -'Invalid' tab to see more details, or to reinstall or uninstall this plugin.\ +Plugins showing in red are not loaded because there is a problem. They are also listed \ +on the 'Invalid' tab. Click on the plugin name to see more details, or to reinstall or uninstall this plugin.\ +

\ +" ) ); + + + + mTabDescriptions.insert( "installed_plugins", tr( "

Installed Plugins

\ +\ +

\ +Here you only see plugins installed on your QGIS.\ +

\ +

\ +Click on the name to see details. \ +

\ +

\ +Click the checkbox or doubleclick the name to activate or deactivate the plugin.\ +

\ +

\ +You can change the sorting via the context menu (right click).\

\ " ) ); @@ -40,7 +57,7 @@ plugins are available in the repositories.\ - mTabDescriptions.insert( "get_more_plugins", tr( "

Get more plugins

\ + mTabDescriptions.insert( "not_installed_plugins", tr( "

Not installed plugins

\ \

\ Here you see the list of all plugins available in the repositories, but which are not yet installed.\ diff --git a/src/app/pluginmanager/qgspluginsortfilterproxymodel.cpp b/src/app/pluginmanager/qgspluginsortfilterproxymodel.cpp index 4de93ba72ce..a923bfd55ad 100644 --- a/src/app/pluginmanager/qgspluginsortfilterproxymodel.cpp +++ b/src/app/pluginmanager/qgspluginsortfilterproxymodel.cpp @@ -32,7 +32,7 @@ bool QgsPluginSortFilterProxyModel::filterAcceptsRow( int sourceRow, const QMode { // 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 ) && mAcceptedStatuses.count() > 2 && sourceModel()->data( inx, SPACER_ROLE ).toString() == mAcceptedSpacers ); } return ( filterByStatus( inx ) && sourceModel()->data( inx, filterRole() ).toString().contains( filterRegExp() ) ); diff --git a/src/ui/qgspluginmanagerbase.ui b/src/ui/qgspluginmanagerbase.ui index 9ef061a05c1..212046c22ea 100644 --- a/src/ui/qgspluginmanagerbase.ui +++ b/src/ui/qgspluginmanagerbase.ui @@ -104,6 +104,15 @@ true + + + All + + + + :/images/themes/default/propertyicons/plugins.svg:/images/themes/default/propertyicons/plugins.svg + + Installed @@ -121,14 +130,14 @@ - Get more + Not installed Not installed plugins available for download - :/images/themes/default/propertyicons/plugins.svg:/images/themes/default/propertyicons/plugins.svg + :/images/themes/default/propertyicons/plugin.svg:/images/themes/default/propertyicons/plugin.svg ItemIsSelectable|ItemIsEnabled @@ -556,8 +565,8 @@ 0 0 - 547 - 748 + 352 + 758