[rkward-cvs] SF.net SVN: rkward:[3823] trunk/rkward/rkward/dialogs

tfry at users.sourceforge.net tfry at users.sourceforge.net
Sat Sep 24 13:33:52 UTC 2011


Revision: 3823
          http://rkward.svn.sourceforge.net/rkward/?rev=3823&view=rev
Author:   tfry
Date:     2011-09-24 13:33:52 +0000 (Sat, 24 Sep 2011)
Log Message:
-----------
Assorted improvements to installing / updating packages:
- Improved sorting
- Implemented filtering
- Do away with the 'Fetch List' button

Modified Paths:
--------------
    trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp
    trunk/rkward/rkward/dialogs/rkloadlibsdialog.h

Modified: trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp
===================================================================
--- trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp	2011-09-23 17:41:55 UTC (rev 3822)
+++ trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp	2011-09-24 13:33:52 UTC (rev 3823)
@@ -29,6 +29,7 @@
 #include <QCloseEvent>
 #include <QSortFilterProxyModel>
 #include <QApplication>
+#include <QLineEdit>
 
 #include <klocale.h>
 #include <kmessagebox.h>
@@ -89,8 +90,7 @@
 	RK_TRACE (DIALOGS);
 
 	if (!currentPage ()) return;
-	// This, and most other focus operations in this file, is to make the keyboard search feature of the QTreeWidget's work (without having to click the lists, first)
-	currentPage ()->widget ()->setFocus ();
+	QTimer::singleShot (0, currentPage ()->widget (), SLOT (activated()));
 }
 
 //static
@@ -108,7 +108,7 @@
 void RKLoadLibsDialog::automatedInstall () {
 	RK_TRACE (DIALOGS);
 
-	install_packages_widget->getListButtonClicked ();
+	install_packages_widget->initialize ();
 	install_packages_widget->trySelectPackage (auto_install_package);
 }
 
@@ -314,7 +314,6 @@
 	installed_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
 	instvbox->addWidget (label);
 	instvbox->addWidget (installed_view);
-	setFocusProxy (installed_view);
 
 	load_button = new QPushButton (RKStandardIcons::getIcon (RKStandardIcons::ActionAddRight), i18n ("Load"), this);
 	connect (load_button, SIGNAL (clicked ()), this, SLOT (loadButtonClicked ()));
@@ -348,6 +347,12 @@
 	RK_TRACE (DIALOGS);
 }
 
+void LoadUnloadWidget::activated () {
+	RK_TRACE (DIALOGS);
+
+	installed_view->setFocus ();
+}
+
 void LoadUnloadWidget::rCommandDone (RCommand *command) {
 	RK_TRACE (DIALOGS);
 	if (command->failed ()) return;
@@ -526,8 +531,7 @@
 	
 	QVBoxLayout *mvbox = new QVBoxLayout (this);
 	mvbox->setContentsMargins (0, 0, 0, 0);
-	QLabel *label = new QLabel (i18n ("Many packages are available on CRAN (Comprehensive R Archive Network), and other repositories (click \"Configure Repositories\" to add more sources). Click \"Fetch List\" to find out, which packages are available. This feature requires a working internet connection."), this);
-	label->setWordWrap (true);
+	QLabel *label = new QLabel (i18n ("Many packages are available on CRAN (Comprehensive R Archive Network), and other repositories<br>(click \"Configure Repositories\" to add more sources)."), this);
 	mvbox->addWidget (label);
 	QHBoxLayout *hbox = new QHBoxLayout ();
 	mvbox->addLayout (hbox);
@@ -536,26 +540,36 @@
 	packages_status = new RKRPackageInstallationStatus (this);
 	packages_view = new QTreeView (this);
 	packages_view->setSortingEnabled (true);
-	model = new QSortFilterProxyModel (this);
+	model = new RKRPackageInstallationStatusSortFilterModel (this);
 	model->setSourceModel (packages_status);
+	model->setFilterCaseSensitivity (Qt::CaseInsensitive);
+	model->setSortCaseSensitivity (Qt::CaseInsensitive);
 	packages_view->setModel (model);
+	packages_view->setEnabled (false);
+	packages_view->setMinimumHeight (packages_view->sizeHintForRow (0) * 15);	// force a decent height
 	hbox->addWidget (packages_view);
-	setFocusProxy (packages_view);
 
 	QVBoxLayout *buttonvbox = new QVBoxLayout ();
 	hbox->addLayout (buttonvbox);
 	buttonvbox->setContentsMargins (0, 0, 0, 0);
-	get_list_button = new QPushButton (i18n ("Fetch list"), this);
-	connect (get_list_button, SIGNAL (clicked ()), this, SLOT (getListButtonClicked ()));
+	label = new QLabel (i18n ("Show only packages matching:"), this);
+	filter_edit = new QLineEdit ("*", this);
+	connect (filter_edit, SIGNAL (textChanged(const QString&)), this, SLOT (filterStringChanged(const QString&)));
+	filterStringChanged (filter_edit->text ());
+
+	mark_all_updates_button = new QPushButton (i18n ("Select all updates"), this);
+	connect (mark_all_updates_button, SIGNAL (clicked()), this, SLOT (markAllUpdates()));
+
 	install_params = new PackageInstallParamsWidget (this, true);
 	connect (parent, SIGNAL (libraryLocationsChanged (const QStringList &)), install_params, SLOT (liblocsChanged (const QStringList &)));
 
-	buttonvbox->addWidget (get_list_button);
+	buttonvbox->addWidget (label);
+	buttonvbox->addWidget (filter_edit);
 	buttonvbox->addStretch (1);
+	buttonvbox->addWidget (mark_all_updates_button);
+	buttonvbox->addStretch (1);
 	buttonvbox->addWidget (install_params);
 	buttonvbox->addStretch (1);
-	
-	packages_view->setEnabled (false);
 
 	connect (dialog, SIGNAL (okClicked ()), this, SLOT (ok ()));
 	connect (dialog, SIGNAL (applyClicked ()), this, SLOT (apply ()));
@@ -567,7 +581,13 @@
 	RK_TRACE (DIALOGS);
 }
 
+void InstallPackagesWidget::activated () {
+	RK_TRACE (DIALOGS);
 
+	filter_edit->setFocus ();
+	if (!packages_status->initialized ()) initialize ();
+}
+
 void InstallPackagesWidget::installPackages (const QStringList &list) {
 	RK_TRACE (DIALOGS);
 	bool as_root = false;
@@ -578,15 +598,22 @@
 	parent->installPackages (list, install_params->libraryLocation (), install_params->installDependencies (), as_root, packages_status->currentRepositories ());
 }
 
-void InstallPackagesWidget::getListButtonClicked () {
+void InstallPackagesWidget::initialize () {
 	RK_TRACE (DIALOGS);
 
 	packages_status->initialize (parent->chain);
-	get_list_button->setEnabled (false);
 	packages_view->setEnabled (true);
 	for (int i = 0; i <= RKRPackageInstallationStatus::PackageName; ++i) packages_view->resizeColumnToContents (i);
 }
 
+void InstallPackagesWidget::filterStringChanged (const QString& new_filter) {
+	RK_TRACE (DIALOGS);
+
+	QString f = new_filter;
+	if (f.isEmpty ()) f = "*";
+	model->setFilterWildcard (f);
+}
+
 void InstallPackagesWidget::trySelectPackage (const QString &package_name) {
 	RK_TRACE (DIALOGS);
 
@@ -598,17 +625,32 @@
 	}
 }
 
-void InstallPackagesWidget::apply () {
+void InstallPackagesWidget::markAllUpdates () {
 	RK_TRACE (DIALOGS);
 
+	QModelIndex index = packages_status->markAllUpdatesForInstallation ();
+	packages_view->setExpanded (model->mapFromSource (index), true);
+	packages_view->scrollTo (model->mapFromSource (index));
+}
+
+void InstallPackagesWidget::doInstall () {
+	RK_TRACE (DIALOGS);
+
 	installPackages (packages_status->packagesToInstall ());
 	packages_status->clearStatus ();
 }
 
+void InstallPackagesWidget::apply () {
+	RK_TRACE (DIALOGS);
+
+	doInstall ();
+	initialize ();	// refresh list
+}
+
 void InstallPackagesWidget::ok () {
 	RK_TRACE (DIALOGS);
 
-	apply ();
+	doInstall ();
 	deleteLater ();
 }
 
@@ -699,12 +741,23 @@
 
 RKRPackageInstallationStatus::RKRPackageInstallationStatus (QObject* parent) : QAbstractItemModel (parent) {
 	RK_TRACE (DIALOGS);
+	_initialized = false;
 }
 
 RKRPackageInstallationStatus::~RKRPackageInstallationStatus () {
 	RK_TRACE (DIALOGS);
 }
 
+QModelIndex RKRPackageInstallationStatus::markAllUpdatesForInstallation () {
+	RK_TRACE (DIALOGS);
+
+	// inefficient, but so what...
+	for (int i = updateable_packages_in_installed.count (); i >= 0; --i) {
+		markPackageForInstallation (installed_packages[updateable_packages_in_installed[i]]);
+	}
+	return index (UpdateablePackages, 0, QModelIndex ());
+}
+
 QModelIndex RKRPackageInstallationStatus::markPackageForInstallation (const QString& package_name) {
 	RK_TRACE (DIALOGS);
 
@@ -737,9 +790,11 @@
 void RKRPackageInstallationStatus::initialize (RCommandChain *chain) {
 	RK_TRACE (DIALOGS);
 
+	_initialized = true;	// will be re-set to false, should the command fail / be cancelled
+
 	RCommand *command = new RCommand (".rk.get.package.intallation.state ()", RCommand::App | RCommand::GetStructuredData);
 	connect (command->notifier (), SIGNAL (commandFinished(RCommand*)), this, SLOT (statusCommandFinished(RCommand*)));
-	RKProgressControl *control = new RKProgressControl (this, i18n ("Please stand by while downloading the list of available packages."), i18n ("Fetching list"), RKProgressControl::CancellableProgress | RKProgressControl::AutoCancelCommands);
+	RKProgressControl *control = new RKProgressControl (this, i18n ("<p>Please stand by while searching for installed and available packages.</p><p><strong>Note:</strong> This requires a working internet connection.</p>"), i18n ("Searching for packages"), RKProgressControl::CancellableProgress | RKProgressControl::AutoCancelCommands);
 	control->addRCommand (command, true);
 	RKGlobals::rInterface ()->issueCommand (command, chain);
 	control->doModal (true);
@@ -750,6 +805,7 @@
 
 	if (!command->succeeded ()) {
 		RK_ASSERT (false);
+		_initialized = false;
 		return;
 	}
 	RK_ASSERT (command->getDataType () == RCommand::StructureVector);
@@ -814,7 +870,7 @@
 
 	int row = parent.row ();
 	if (row == UpdateablePackages) return updateable_packages_in_available.count ();
-	if (row == NewPackages) return available_packages.count ();
+	if (row == NewPackages) return new_packages_in_available.count ();
 	if (row == InstalledPackages) return installed_packages.count ();
 
 	RK_ASSERT (false);
@@ -864,10 +920,11 @@
 			}
 		} else if (col == EnhancesRKWard) {
 			if (role == Qt::DisplayRole) return QVariant (QString (" "));	// must have a placeholder, here, or Qt will collapse the column
-			if (role == Qt::DecorationRole) {
+			if ((role == Qt::DecorationRole) || (role == Qt::UserRole)) {
 				bool enhance_rk;
 				if (prow == InstalledPackages) enhance_rk = enhance_rk_in_installed.value (irow);
 				else enhance_rk = enhance_rk_in_available.value (arow);
+				if (role == Qt::UserRole) return QVariant (enhance_rk);
 				if (enhance_rk) return QApplication::windowIcon ();
 			}
 		} else if (col == PackageName) {
@@ -990,4 +1047,33 @@
 	return anyfound;
 }
 
+
+RKRPackageInstallationStatusSortFilterModel::RKRPackageInstallationStatusSortFilterModel (QObject* parent) : QSortFilterProxyModel (parent) {
+	RK_TRACE (DIALOGS);
+}
+
+RKRPackageInstallationStatusSortFilterModel::~RKRPackageInstallationStatusSortFilterModel () {
+	RK_TRACE (DIALOGS);
+}
+
+bool RKRPackageInstallationStatusSortFilterModel::lessThan (const QModelIndex &left, const QModelIndex &right) const {
+	if (!left.parent ().isValid ()) {		// Disable sorting for the top level items
+		return (left.row () > right.row ());
+	}
+	if (left.column () == RKRPackageInstallationStatus::EnhancesRKWard) {
+		return (!left.data (Qt::UserRole).toBool ());
+	}
+	return QSortFilterProxyModel::lessThan (left, right);
+}
+
+bool RKRPackageInstallationStatusSortFilterModel::filterAcceptsRow (int source_row, const QModelIndex &source_parent) const {
+	if (!source_parent.isValid ()) return true;		// Never filter the top level item
+
+// filter on Name and Title
+	QString name = source_parent.child (source_row, RKRPackageInstallationStatus::PackageName).data ().toString ();
+	if (filterRegExp ().exactMatch (name)) return true;
+	QString title = source_parent.child (source_row, RKRPackageInstallationStatus::PackageTitle).data ().toString ();
+	return (filterRegExp ().exactMatch (title));
+}
+
 #include "rkloadlibsdialog.moc"

Modified: trunk/rkward/rkward/dialogs/rkloadlibsdialog.h
===================================================================
--- trunk/rkward/rkward/dialogs/rkloadlibsdialog.h	2011-09-23 17:41:55 UTC (rev 3822)
+++ trunk/rkward/rkward/dialogs/rkloadlibsdialog.h	2011-09-24 13:33:52 UTC (rev 3823)
@@ -21,10 +21,12 @@
 
 #include <qstringlist.h>
 #include <QProcess>
+#include <QSortFilterProxyModel>
 
 #include "../settings/rksettingsmoduler.h"
 #include "../rbackend/rcommandreceiver.h"
 
+class QLineEdit;
 class QTreeView;
 class QTreeWidget;
 class QSortFilterProxyModel;
@@ -119,6 +121,7 @@
 	void cancel ();
 	void updateInstalledPackages ();
 	void updateButtons ();
+	void activated ();
 protected:
 	void rCommandDone (RCommand *command);
 private:
@@ -184,9 +187,13 @@
 /** mark a package for installation.
  * @returns the index of the package, if the package is available, an invalid index, if it is not available */
 	QModelIndex markPackageForInstallation (const QString& package_name);
+/** mark all available updates for installation.
+ * @returns the index of the "Updateable Packages" item */
+	QModelIndex markAllUpdatesForInstallation ();
 /** reset all installation states to NoAction */
 	void clearStatus ();
 	QStringList currentRepositories () const { return current_repos; };
+	bool initialized () const { return _initialized; };
 private slots:
 	void statusCommandFinished (RCommand *command);
 private:
@@ -200,10 +207,20 @@
 	QVector<PackageStatusChange> installed_status;
 	QVector<PackageStatusChange> available_status;
 	QVector<bool> installed_has_update;
+	bool _initialized;
 
 	QStringList current_repos;
 };
 
+class RKRPackageInstallationStatusSortFilterModel : public QSortFilterProxyModel {
+public:
+	RKRPackageInstallationStatusSortFilterModel (QObject* parent = 0);
+	~RKRPackageInstallationStatusSortFilterModel ();
+protected:
+	bool lessThan (const QModelIndex &left, const QModelIndex &right) const;
+	bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const;
+};
+
 /**
 Allows the user to update / install R packages.
 To be used in RKLoadLibsDialog.
@@ -217,18 +234,23 @@
 	
 	~InstallPackagesWidget ();
 	void trySelectPackage (const QString &package_name);
+	void initialize ();
 public slots:
-	void getListButtonClicked ();
 	void ok ();
 	void apply ();
 	void cancel ();
+	void filterStringChanged (const QString &new_filter);
+	void activated ();
+	void markAllUpdates ();
 private:
+	void doInstall ();
 	void installPackages (const QStringList &list);
 	QTreeView *packages_view;
 	RKRPackageInstallationStatus *packages_status;
 	QSortFilterProxyModel *model;
 
-	QPushButton *get_list_button;
+	QPushButton *mark_all_updates_button;
+	QLineEdit *filter_edit;
 	PackageInstallParamsWidget *install_params;
 	
 	RKLoadLibsDialog *parent;

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.





More information about the rkward-tracker mailing list