[rkward-cvs] SF.net SVN: rkward:[3822] trunk/rkward
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Fri Sep 23 17:41:56 UTC 2011
Revision: 3822
http://rkward.svn.sourceforge.net/rkward/?rev=3822&view=rev
Author: tfry
Date: 2011-09-23 17:41:55 +0000 (Fri, 23 Sep 2011)
Log Message:
-----------
Rework package installation dialog. This is still work in progress / not fully implemented.
Modified Paths:
--------------
trunk/rkward/ChangeLog
trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp
trunk/rkward/rkward/dialogs/rkloadlibsdialog.h
trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R
Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog 2011-09-23 14:00:03 UTC (rev 3821)
+++ trunk/rkward/ChangeLog 2011-09-23 17:41:55 UTC (rev 3822)
@@ -1,3 +1,4 @@
+- Reworked package installation / update dialog TODO: implement removing, "check all updateable", clean layout, fix size, more tips, fix sorting
- Fixed: Integrated help browser would not update navigation history when following page internal links
- Documentation on writing RKWard plugins is now accessible, locally
- The file filter for R script files is now configurable, and includes *.Rhistory, by default
Modified: trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp
===================================================================
--- trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp 2011-09-23 14:00:03 UTC (rev 3821)
+++ trunk/rkward/rkward/dialogs/rkloadlibsdialog.cpp 2011-09-23 17:41:55 UTC (rev 3822)
@@ -27,6 +27,8 @@
#include <qtimer.h>
#include <qtextstream.h>
#include <QCloseEvent>
+#include <QSortFilterProxyModel>
+#include <QApplication>
#include <klocale.h>
#include <kmessagebox.h>
@@ -63,10 +65,8 @@
addPage (luwidget, i18n ("Local packages"));
connect (this, SIGNAL (installedPackagesChanged ()), luwidget, SLOT (updateInstalledPackages ()));
- addPage (new UpdatePackagesWidget (this), i18n ("Update"));
-
install_packages_widget = new InstallPackagesWidget (this);
- install_packages_pageitem = addPage (install_packages_widget, i18n ("Install"));
+ install_packages_pageitem = addPage (install_packages_widget, i18n ("Install / Update / Remove"));
setButtonText (KDialog::User1, i18n ("Configure Repositories"));
@@ -172,7 +172,7 @@
}
}
-bool RKLoadLibsDialog::installPackages (const QStringList &packages, const QString &to_libloc, bool install_dependencies, bool as_root) {
+bool RKLoadLibsDialog::installPackages (const QStringList &packages, const QString &to_libloc, bool install_dependencies, bool as_root, const QStringList& repos) {
RK_TRACE (DIALOGS);
if (packages.isEmpty ()) return false;
@@ -185,6 +185,13 @@
if (install_dependencies) command_string += ", dependencies=TRUE";
command_string += ")\n";
+ QString repos_string = "options (repos= c(";
+ for (int i = 0; i < repos.count (); ++i) {
+ if (i) repos_string.append (", ");
+ repos_string.append (RObject::rQuote (repos[i]));
+ }
+ repos_string.append ("))\n");
+
// TODO: won't work with some versions of GCC (which ones exactly)?
// QFile file (QDir (RKSettingsModuleGeneral::filesPath ()).filePath ("install_script.R"));
// WORKAROUND:
@@ -193,7 +200,7 @@
// WORKADOUND END
if (file.open (QIODevice::WriteOnly)) {
QTextStream stream (&file);
- stream << "options (repos=" + repos_string + ")\n" + command_string;
+ stream << repos_string + command_string;
if (as_root) {
#ifdef Q_WS_WIN
RK_ASSERT (false);
@@ -510,170 +517,9 @@
deleteLater ();
}
-/////////////////////// UpdatePackagesWidget //////////////////////////
-#define FIND_OLD_PACKAGES_COMMAND 1
-
-UpdatePackagesWidget::UpdatePackagesWidget (RKLoadLibsDialog *dialog) : QWidget (0) {
- RK_TRACE (DIALOGS);
- UpdatePackagesWidget::parent = dialog;
-
- QVBoxLayout *mvbox = new QVBoxLayout (this);
- mvbox->setContentsMargins (0, 0, 0, 0);
- QLabel *label = new QLabel (i18n ("In order to find out, which of your installed packaged have an update available, click \"Fetch List\". This feature requires a working internet connection."), this);
- label->setWordWrap (true);
- mvbox->addWidget (label);
-
- QHBoxLayout *hbox = new QHBoxLayout ();
- mvbox->addLayout (hbox);
- hbox->setContentsMargins (0, 0, 0, 0);
-
- updateable_view = new QTreeWidget (this);
- updateable_view->setHeaderLabels (QStringList () << i18n ("Name") << i18n ("Location") << i18n ("Local Version") << i18n ("Online Version"));
- updateable_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
- hbox->addWidget (updateable_view);
- setFocusProxy (updateable_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 ()));
- update_selected_button = new QPushButton (i18n ("Update Selected"), this);
- connect (update_selected_button, SIGNAL (clicked ()), this, SLOT (updateSelectedButtonClicked ()));
- update_all_button = new QPushButton (i18n ("Update All"), this);
- connect (update_all_button, SIGNAL (clicked ()), this, SLOT (updateAllButtonClicked ()));
- install_params = new PackageInstallParamsWidget (this, false);
- connect (parent, SIGNAL (libraryLocationsChanged (const QStringList &)), install_params, SLOT (liblocsChanged (const QStringList &)));
-
- buttonvbox->addWidget (get_list_button);
- buttonvbox->addStretch (1);
- buttonvbox->addWidget (update_selected_button);
- buttonvbox->addWidget (update_all_button);
- buttonvbox->addStretch (1);
- buttonvbox->addWidget (install_params);
- buttonvbox->addStretch (1);
-
- update_selected_button->setEnabled (false);
- update_all_button->setEnabled (false);
- updateable_view->setEnabled (false);
-
- new QTreeWidgetItem (updateable_view, QStringList ("...")); // i18n ("[Click \"Fetch list\" for updates]")
-
- connect (dialog, SIGNAL (okClicked ()), this, SLOT (ok ()));
- connect (dialog, SIGNAL (cancelClicked ()), this, SLOT (cancel ()));
- connect (this, SIGNAL (destroyed ()), dialog, SLOT (childDeleted ()));
-}
-
-UpdatePackagesWidget::~UpdatePackagesWidget () {
- RK_TRACE (DIALOGS);
-}
-
-void UpdatePackagesWidget::rCommandDone (RCommand *command) {
- RK_TRACE (DIALOGS);
- if (command->getFlags () == FIND_OLD_PACKAGES_COMMAND) {
- if (!command->failed ()) {
- updateable_view->clear ();
-
- RK_ASSERT (command->getDataLength () == 5);
- RData *package = command->getStructureVector ()[0];
- RData *libpath = command->getStructureVector ()[1];
- RData *installed = command->getStructureVector ()[2];
- RData *reposver = command->getStructureVector ()[3];
- RData *reposstring = command->getStructureVector ()[4];
-
- unsigned int count = package->getDataLength ();
- RK_ASSERT (count == libpath->getDataLength ());
- RK_ASSERT (count == installed->getDataLength ());
- RK_ASSERT (count == reposver->getDataLength ());
- for (unsigned int i=0; i < count; ++i) {
- QTreeWidgetItem* item = new QTreeWidgetItem (updateable_view);
- item->setText (0, package->getStringVector ()[i]);
- item->setText (1, libpath->getStringVector ()[i]);
- item->setText (2, installed->getStringVector ()[i]);
- item->setText (3, reposver->getStringVector ()[i]);
- }
-
- if (updateable_view->topLevelItemCount ()) {
- update_selected_button->setEnabled (true);
- update_all_button->setEnabled (true);
- updateable_view->setEnabled (true);
- updateable_view->setFocus ();
- updateable_view->setSortingEnabled (true);
- updateable_view->sortItems (0, Qt::AscendingOrder);
- } else {
- new QTreeWidgetItem (updateable_view, QStringList (i18n ("[No updates available]")));
- }
- updateable_view->resizeColumnToContents (0);
-
- RK_ASSERT (reposstring->getDataLength () == 1);
- // this is after the repository was chosen. Update the repository string.
- parent->repos_string = reposstring->getStringVector ()[0];
- } else {
- get_list_button->setEnabled (true);
- }
- } else {
- RK_ASSERT (false);
- }
-}
-
-void UpdatePackagesWidget::updatePackages (const QStringList &list) {
- RK_TRACE (DIALOGS);
- bool as_root = false;
-
- if (list.isEmpty ()) return;
- if (!install_params->checkWritable (&as_root)) return;
-
- parent->installPackages (list, install_params->libraryLocation (), install_params->installDependencies (), as_root);
-}
-
-void UpdatePackagesWidget::updateSelectedButtonClicked () {
- RK_TRACE (DIALOGS);
- QStringList list;
- QList<QTreeWidgetItem*> selected = updateable_view->selectedItems ();
- for (int i = 0; i < selected.count (); ++i) {
- list.append (selected[i]->text (0));
- }
- updatePackages (list);
-}
-
-void UpdatePackagesWidget::updateAllButtonClicked () {
- RK_TRACE (DIALOGS);
- QStringList list;
- for (int i = 0; i < updateable_view->topLevelItemCount (); ++i) {
- list.append (updateable_view->topLevelItem (i)->text (0));
- }
- updatePackages (list);
-}
-
-void UpdatePackagesWidget::getListButtonClicked () {
- RK_TRACE (DIALOGS);
-
- get_list_button->setEnabled (false);
-
- RCommand *command = new RCommand (".rk.get.old.packages ()", RCommand::App | RCommand::GetStructuredData, QString::null, this, FIND_OLD_PACKAGES_COMMAND);
-
- RKProgressControl *control = new RKProgressControl (this, i18n ("Please stand by while determining, which packages have an update available online."), i18n ("Fetching list"), RKProgressControl::CancellableProgress | RKProgressControl::AutoCancelCommands);
- control->addRCommand (command, true);
- RKGlobals::rInterface ()->issueCommand (command, parent->chain);
- control->doModal (true);
-}
-
-void UpdatePackagesWidget::ok () {
- RK_TRACE (DIALOGS);
- deleteLater ();
-}
-
-void UpdatePackagesWidget::cancel () {
- RK_TRACE (DIALOGS);
- deleteLater ();
-}
-
-
/////////////////////// InstallPackagesWidget //////////////////////////
-#define FIND_AVAILABLE_PACKAGES_COMMAND 1
-
InstallPackagesWidget::InstallPackagesWidget (RKLoadLibsDialog *dialog) : QWidget (0) {
RK_TRACE (DIALOGS);
InstallPackagesWidget::parent = dialog;
@@ -686,36 +532,33 @@
QHBoxLayout *hbox = new QHBoxLayout ();
mvbox->addLayout (hbox);
hbox->setContentsMargins (0, 0, 0, 0);
-
- installable_view = new QTreeWidget (this);
- installable_view->setHeaderLabels (QStringList () << i18n ("Name") << i18n ("Version"));
- installable_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
- hbox->addWidget (installable_view);
- setFocusProxy (installable_view);
+ packages_status = new RKRPackageInstallationStatus (this);
+ packages_view = new QTreeView (this);
+ packages_view->setSortingEnabled (true);
+ model = new QSortFilterProxyModel (this);
+ model->setSourceModel (packages_status);
+ packages_view->setModel (model);
+ 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 ()));
- install_selected_button = new QPushButton (i18n ("Install Selected"), this);
- connect (install_selected_button, SIGNAL (clicked ()), this, SLOT (installSelectedButtonClicked ()));
install_params = new PackageInstallParamsWidget (this, true);
connect (parent, SIGNAL (libraryLocationsChanged (const QStringList &)), install_params, SLOT (liblocsChanged (const QStringList &)));
buttonvbox->addWidget (get_list_button);
buttonvbox->addStretch (1);
- buttonvbox->addWidget (install_selected_button);
- buttonvbox->addStretch (1);
buttonvbox->addWidget (install_params);
buttonvbox->addStretch (1);
- install_selected_button->setEnabled (false);
- installable_view->setEnabled (false);
+ packages_view->setEnabled (false);
- new QTreeWidgetItem (installable_view, QStringList ("...")); // i18n ("[Click \"Fetch list\" to see available packages]")
-
connect (dialog, SIGNAL (okClicked ()), this, SLOT (ok ()));
+ connect (dialog, SIGNAL (applyClicked ()), this, SLOT (apply ()));
connect (dialog, SIGNAL (cancelClicked ()), this, SLOT (cancel ()));
connect (this, SIGNAL (destroyed ()), dialog, SLOT (childDeleted ()));
}
@@ -724,49 +567,7 @@
RK_TRACE (DIALOGS);
}
-void InstallPackagesWidget::rCommandDone (RCommand *command) {
- RK_TRACE (DIALOGS);
- if (command->getFlags () == FIND_AVAILABLE_PACKAGES_COMMAND) {
- if (!command->failed ()) {
- installable_view->clear ();
- RK_ASSERT (command->getDataLength () == 3);
-
- RData *names = command->getStructureVector ()[0];
- RData *versions = command->getStructureVector ()[1];
- RData *repos = command->getStructureVector ()[2];
-
- unsigned int count = names->getDataLength ();
- RK_ASSERT (count == versions->getDataLength ());
- RK_ASSERT (repos->getDataLength () == 1);
-
- for (unsigned int i=0; i < count; ++i) {
- QTreeWidgetItem* item = new QTreeWidgetItem (installable_view);
- item->setText (0, names->getStringVector ()[i]);
- item->setText (1, versions->getStringVector ()[i]);
- }
-
- if (installable_view->topLevelItemCount ()) {
- install_selected_button->setEnabled (true);
- installable_view->setEnabled (true);
- installable_view->setFocus ();
- installable_view->setSortingEnabled (true);
- installable_view->sortItems (0, Qt::AscendingOrder);
- } else {
- new QTreeWidgetItem (installable_view, QStringList (i18n ("[No packages available]")));
- }
- installable_view->resizeColumnToContents (0);
-
- // this is after the repository was chosen. Update the repository string.
- parent->repos_string = repos->getStringVector ()[0];
- } else {
- get_list_button->setEnabled (true);
- }
- } else {
- RK_ASSERT (false);
- }
-}
-
void InstallPackagesWidget::installPackages (const QStringList &list) {
RK_TRACE (DIALOGS);
bool as_root = false;
@@ -774,47 +575,40 @@
if (list.isEmpty ()) return;
if (!install_params->checkWritable (&as_root)) return;
- parent->installPackages (list, install_params->libraryLocation (), install_params->installDependencies (), as_root);
+ parent->installPackages (list, install_params->libraryLocation (), install_params->installDependencies (), as_root, packages_status->currentRepositories ());
}
-void InstallPackagesWidget::installSelectedButtonClicked () {
- RK_TRACE (DIALOGS);
- QStringList list;
- QList<QTreeWidgetItem*> selected = installable_view->selectedItems ();
- for (int i = 0; i < selected.count (); ++i) {
- list.append (selected[i]->text (0));
- }
- installPackages (list);
-}
-
void InstallPackagesWidget::getListButtonClicked () {
RK_TRACE (DIALOGS);
+ packages_status->initialize (parent->chain);
get_list_button->setEnabled (false);
-
- RCommand *command = new RCommand (".rk.get.available.packages ()", RCommand::App | RCommand::GetStructuredData, QString::null, this, FIND_AVAILABLE_PACKAGES_COMMAND);
- RKProgressControl *control = new RKProgressControl (this, i18n ("Please stand by while downloading the list of available packages."), i18n ("Fetching list"), RKProgressControl::CancellableProgress | RKProgressControl::AutoCancelCommands);
- control->addRCommand (command, true);
- RKGlobals::rInterface ()->issueCommand (command, parent->chain);
- control->doModal (true);
+ packages_view->setEnabled (true);
+ for (int i = 0; i <= RKRPackageInstallationStatus::PackageName; ++i) packages_view->resizeColumnToContents (i);
}
void InstallPackagesWidget::trySelectPackage (const QString &package_name) {
RK_TRACE (DIALOGS);
- QList<QTreeWidgetItem*> found = installable_view->findItems (package_name, Qt::MatchExactly, 0);
- if (found.isEmpty ()) {
+ QModelIndex index = packages_status->markPackageForInstallation (package_name);
+ if (!index.isValid ()) {
KMessageBox::sorry (0, i18n ("The package requested by the backend (\"%1\") was not found in the package repositories. Maybe the package name was mis-spelled. Or maybe you need to add additional repositories via the \"Configure Repositories\"-button.", package_name), i18n ("Package not available"));
} else {
- RK_ASSERT (found.count () == 1);
- installable_view->setCurrentItem (found[0]);
- found[0]->setSelected (true);
- installable_view->scrollToItem (found[0]);
+ packages_view->scrollTo (model->mapFromSource (index));
}
}
+void InstallPackagesWidget::apply () {
+ RK_TRACE (DIALOGS);
+
+ installPackages (packages_status->packagesToInstall ());
+ packages_status->clearStatus ();
+}
+
void InstallPackagesWidget::ok () {
RK_TRACE (DIALOGS);
+
+ apply ();
deleteLater ();
}
@@ -901,4 +695,299 @@
libloc_selector->insertItems (0, newlist);
}
+/////////// RKRPackageInstallationStatus /////////////////
+
+RKRPackageInstallationStatus::RKRPackageInstallationStatus (QObject* parent) : QAbstractItemModel (parent) {
+ RK_TRACE (DIALOGS);
+}
+
+RKRPackageInstallationStatus::~RKRPackageInstallationStatus () {
+ RK_TRACE (DIALOGS);
+}
+
+QModelIndex RKRPackageInstallationStatus::markPackageForInstallation (const QString& package_name) {
+ RK_TRACE (DIALOGS);
+
+ // is the package available at all?
+ QModelIndex pindex;
+ int row = available_packages.indexOf (package_name);
+ if (row < 0) return pindex;
+
+ // find out, whether it is a new or and updateable package
+ QModelIndex parent;
+ int urow = updateable_packages_in_available.indexOf (row);
+ if (urow >= 0) {
+ parent = index (UpdateablePackages, 0);
+ row = urow;
+ } else {
+ row = new_packages_in_available.indexOf (row);
+ parent = index (NewPackages, 0);
+ }
+ if (row < 0) {
+ RK_ASSERT (false);
+ return pindex;
+ }
+
+ // mark for installation
+ pindex = index (row, InstallationStatus, parent);
+ setData (pindex, QVariant (Qt::Checked), Qt::CheckStateRole);
+ return pindex;
+}
+
+void RKRPackageInstallationStatus::initialize (RCommandChain *chain) {
+ RK_TRACE (DIALOGS);
+
+ 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);
+ control->addRCommand (command, true);
+ RKGlobals::rInterface ()->issueCommand (command, chain);
+ control->doModal (true);
+}
+
+void RKRPackageInstallationStatus::statusCommandFinished (RCommand *command) {
+ RK_TRACE (DIALOGS);
+
+ if (!command->succeeded ()) {
+ RK_ASSERT (false);
+ return;
+ }
+ RK_ASSERT (command->getDataType () == RCommand::StructureVector);
+ RK_ASSERT (command->getDataLength () == 4);
+
+ RData::RDataStorage top = command->getStructureVector ();
+ RData::RDataStorage available = top[0]->getStructureVector ();
+ available_packages = available[0]->getStringVector ();
+ available_titles = available[1]->getStringVector ();
+ available_versions = available[2]->getStringVector ();
+ available_repos = available[3]->getStringVector ();
+ enhance_rk_in_available = available[4]->getIntVector ();
+
+ RData::RDataStorage installed = top[1]->getStructureVector ();
+ installed_packages = installed[0]->getStringVector ();
+ installed_titles = installed[1]->getStringVector ();
+ installed_versions = installed[2]->getStringVector ();
+ installed_libpaths = installed[3]->getStringVector ();
+ enhance_rk_in_installed = installed[4]->getIntVector ();
+ installed_has_update.fill (false, installed_packages.count ());
+
+ new_packages_in_available = top[2]->getIntVector ();
+ RData::RDataStorage updateable = top[3]->getStructureVector ();
+ updateable_packages_in_installed = updateable[0]->getIntVector ();
+ updateable_packages_in_available = updateable[1]->getIntVector ();
+
+ for (int i = updateable_packages_in_installed.count () - 1; i >= 0; --i) {
+ installed_has_update[updateable_packages_in_installed[i]] = true;
+ }
+
+ current_repos = top[4]->getStringVector ();
+
+ clearStatus ();
+}
+
+void RKRPackageInstallationStatus::clearStatus () {
+ RK_TRACE (DIALOGS);
+
+ available_status.fill (NoAction, available_packages.count ());
+ installed_status.fill (NoAction, installed_packages.count ());
+ reset ();
+}
+
+QVariant RKRPackageInstallationStatus::headerData (int section, Qt::Orientation orientation, int role) const {
+ if (orientation != Qt::Horizontal) return QVariant ();
+
+ if ((role == Qt::DecorationRole) && (section == EnhancesRKWard)) return QApplication::windowIcon ();
+
+ if (role == Qt::DisplayRole) {
+ if (section == InstallationStatus) return QVariant (i18n ("Status"));
+ if (section == PackageName) return QVariant (i18n ("Name"));
+ if (section == PackageTitle) return QVariant (i18n ("Title"));
+ if (section == Version) return QVariant (i18n ("Version"));
+ if (section == Location) return QVariant (i18n ("Location"));
+ }
+ return QVariant ();
+}
+
+int RKRPackageInstallationStatus::rowCount (const QModelIndex &parent) const {
+ if (!parent.isValid ()) return TOPLEVELITEM_COUNT; // top level
+ if (parent.parent ().isValid ()) return 0; // model has exactly two levels
+
+ int row = parent.row ();
+ if (row == UpdateablePackages) return updateable_packages_in_available.count ();
+ if (row == NewPackages) return available_packages.count ();
+ if (row == InstalledPackages) return installed_packages.count ();
+
+ RK_ASSERT (false);
+ return 0;
+}
+
+QVariant RKRPackageInstallationStatus::data (const QModelIndex &index, int role) const {
+ if (!index.isValid ()) return QVariant ();
+ if (!index.parent ().isValid ()) { // top level item
+ int row = index.row ();
+ if (row == UpdateablePackages) {
+ if ((role == Qt::DisplayRole) && (index.column () == PackageName)) return QVariant (i18n ("Updateable Packages"));
+ if (role == Qt::ToolTipRole) return QVariant (i18n ("Packages for which an update is available. This may include packages which were merely built against a newer version of R."));
+ } else if (row == NewPackages) {
+ if ((role == Qt::DisplayRole) && (index.column () == PackageName)) return QVariant (i18n ("New Packages"));
+ if (role == Qt::ToolTipRole) return QVariant (i18n ("Packages for which available for installation, but which are not currently installed."));
+ } else if (row == InstalledPackages) {
+ if ((role == Qt::DisplayRole) && (index.column () == PackageName)) return QVariant (i18n ("Installed Packages"));
+ if (role == Qt::ToolTipRole) return QVariant (i18n ("Packages for which installed locally. Note that updates may be available for these packages."));
+ }
+ if (role == Qt::BackgroundColorRole) return QVariant (QColor (200, 200, 200));
+ } else if (!index.parent ().parent ().isValid ()) { // model has exactly two levels
+ int col = index.column ();
+ int prow = index.parent ().row ();
+ int arow, irow; // row numbers in the lists of available_packages / installed_packages
+ if (prow == UpdateablePackages) {
+ arow = updateable_packages_in_available.value (index.row ());
+ irow = updateable_packages_in_installed.value (index.row ());
+ } else if (prow == NewPackages) arow = new_packages_in_available.value (index.row ());
+ else irow = index.row ();
+
+ if (col == InstallationStatus) {
+ PackageStatusChange stat;
+ if (prow == InstalledPackages) stat = installed_status.value (irow, NoAction);
+ else stat = available_status.value (arow, NoAction);
+ if (stat == NoAction) {
+ if (role == Qt::CheckStateRole) {
+ if (prow == InstalledPackages) return Qt::PartiallyChecked;
+ return Qt::Unchecked;
+ }
+ } else if (stat == Install) {
+ if (role == Qt::CheckStateRole) return Qt::Checked;
+ if (role == Qt::DisplayRole) return QVariant (i18n ("Install"));
+ } else {
+ if (role == Qt::CheckStateRole) return Qt::Unchecked;
+ if (role == Qt::DisplayRole) return QVariant (i18n ("Remove"));
+ }
+ } 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) {
+ bool enhance_rk;
+ if (prow == InstalledPackages) enhance_rk = enhance_rk_in_installed.value (irow);
+ else enhance_rk = enhance_rk_in_available.value (arow);
+ if (enhance_rk) return QApplication::windowIcon ();
+ }
+ } else if (col == PackageName) {
+ if (role == Qt::DisplayRole) {
+ if (prow == InstalledPackages) return installed_packages.value (irow);
+ else return available_packages.value (arow);
+ }
+ } else if (col == PackageTitle) {
+ if (role == Qt::DisplayRole) {
+ if (prow == InstalledPackages) return installed_titles.value (irow);
+ else return available_titles.value (arow);
+ }
+ } else if (col == Version) {
+ if (role == Qt::DisplayRole) {
+ if (prow == InstalledPackages) return installed_versions.value (irow);
+ else if (prow == NewPackages) return available_versions.value (arow);
+ else return QVariant (installed_versions.value (irow) + " -> " + available_versions.value (arow));
+ }
+ } else if (col == Location) {
+ if (role == Qt::DisplayRole) {
+ if (prow == InstalledPackages) return installed_libpaths.value (irow);
+ else if (prow == NewPackages) return available_repos.value (arow);
+ else return QVariant (installed_libpaths.value (irow) + " -> " + available_repos.value (arow));
+ }
+ }
+ }
+ return QVariant ();
+}
+
+Qt::ItemFlags RKRPackageInstallationStatus::flags (const QModelIndex &index) const {
+ qint64 pos = index.internalId ();
+ Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+ if (pos >= 0) flags |= Qt::ItemIsUserCheckable;
+ if (pos == InstalledPackages) flags |= Qt::ItemIsTristate;
+ return flags;
+}
+
+QModelIndex RKRPackageInstallationStatus::index (int row, int column, const QModelIndex &parent) const {
+ if (!parent.isValid ()) return createIndex (row, column, -1); // toplevel items
+ return createIndex (row, column, parent.row ()); // parent.row () identifies, which toplevel item is the parent.
+}
+
+QModelIndex RKRPackageInstallationStatus::parent (const QModelIndex& index) const {
+ if (index.internalId () == -1) return QModelIndex ();
+ return (RKRPackageInstallationStatus::index (index.internalId (), 0, QModelIndex ()));
+}
+
+bool RKRPackageInstallationStatus::setData (const QModelIndex &index, const QVariant &value, int role) {
+ RK_TRACE (DIALOGS);
+
+ if (role != Qt::CheckStateRole) return false;
+ if (!index.isValid ()) return false;
+ if (!index.parent ().isValid ()) return false;
+ QModelIndex bindex;
+
+ PackageStatusChange stat = NoAction;
+ int irow = -1;
+ int arow = -1;
+ if (value.toInt () == Qt::Checked) stat = Install;
+ else if (value.toInt () == Qt::Unchecked) stat = Remove;
+
+ if (index.internalId () == InstalledPackages) {
+ irow = index.row ();
+ if ((stat == Install) && (installed_status[irow] == Remove)) stat = NoAction;
+ if (installed_has_update.value (irow, false)) {
+ // NOTE: installed, and updatable packages are coupled
+ int urow = updateable_packages_in_installed.indexOf (irow);
+ RK_ASSERT (urow >= 0);
+ arow = updateable_packages_in_available.value (urow);
+ bindex = RKRPackageInstallationStatus::index (urow, InstallationStatus, RKRPackageInstallationStatus::index (UpdateablePackages, 0));
+ }
+ } else {
+ if (stat == Remove) stat = NoAction;
+ if (index.internalId () == UpdateablePackages) {
+ // NOTE: installed, and updatable packages are coupled
+ irow = updateable_packages_in_installed.value (index.row ());
+ arow = updateable_packages_in_available.value (index.row ());
+ bindex = RKRPackageInstallationStatus::index (irow, InstallationStatus, RKRPackageInstallationStatus::index (InstalledPackages, 0));
+ } else {
+ arow = new_packages_in_available.value (index.row ());
+ }
+ }
+
+ if (irow >= 0) installed_status[irow] = stat;
+ if (arow >= 0) available_status[arow] = stat;
+
+ dataChanged (index, index);
+ if (bindex.isValid ()) dataChanged (bindex, bindex);
+
+ return true;
+}
+
+QStringList RKRPackageInstallationStatus::packagesToInstall () const {
+ RK_TRACE (DIALOGS);
+
+ QStringList ret;
+ for (int i = installed_status.count () - 1; i >= 0; --i) {
+ if (installed_status[i] == Install) ret.append (installed_packages[i]);
+ }
+ for (int i = available_status.count () - 1; i >= 0; --i) {
+ if (available_status[i] == Install) {
+ QString package = available_packages[i];
+ if (!ret.contains (package)) ret.append (package);
+ }
+ }
+ return ret;
+}
+
+bool RKRPackageInstallationStatus::packagesToRemove (QStringList *packages, QStringList *liblocs) {
+ RK_TRACE (DIALOGS);
+
+ bool anyfound = false;
+ for (int i = installed_status.count () - 1; i >= 0; --i) {
+ if (installed_status[i] == Remove) {
+ packages->append (installed_packages[i]);
+ liblocs->append (installed_libpaths[i]);
+ anyfound = true;
+ }
+ }
+ return anyfound;
+}
+
#include "rkloadlibsdialog.moc"
Modified: trunk/rkward/rkward/dialogs/rkloadlibsdialog.h
===================================================================
--- trunk/rkward/rkward/dialogs/rkloadlibsdialog.h 2011-09-23 14:00:03 UTC (rev 3821)
+++ trunk/rkward/rkward/dialogs/rkloadlibsdialog.h 2011-09-23 17:41:55 UTC (rev 3822)
@@ -25,8 +25,9 @@
#include "../settings/rksettingsmoduler.h"
#include "../rbackend/rcommandreceiver.h"
+class QTreeView;
class QTreeWidget;
-class QTreeWidgetItem;
+class QSortFilterProxyModel;
class QComboBox;
class QPushButton;
class RKProgressControl;
@@ -54,7 +55,7 @@
~RKLoadLibsDialog ();
- bool installPackages (const QStringList &packages, const QString &to_libloc, bool install_dependencies, bool as_root);
+ bool installPackages (const QStringList &packages, const QString &to_libloc, bool install_dependencies, bool as_root, const QStringList& repos);
/** opens a modal RKLoadLibsDialog with the "Install new Packages" tab on front (To be used when a require () fails in the R backend
@param parent parent QWidget. The dialog will be centered there
@@ -83,7 +84,6 @@
private:
void tryDestruct ();
friend class LoadUnloadWidget;
-friend class UpdatePackagesWidget;
friend class InstallPackagesWidget;
RCommandChain *chain;
@@ -93,7 +93,6 @@
QString auto_install_package;
int num_child_widgets;
bool accepted;
- QString repos_string;
QProcess* installation_process;
};
@@ -137,45 +136,81 @@
RKLoadLibsDialog *parent;
};
-/**
-Shows which packages are can be updated from CRAN.
-Ro be used in RKLoadLibsDialog.
+/** Item model and encapsulation for package status (used in InstallPackagesWidget) */
+class RKRPackageInstallationStatus : public QAbstractItemModel {
+ Q_OBJECT
+public:
+ RKRPackageInstallationStatus (QObject* parent);
+ ~RKRPackageInstallationStatus ();
- at author Thomas Friedrichsmeier
-*/
-class UpdatePackagesWidget : public QWidget, public RCommandReceiver {
-Q_OBJECT
-public:
- UpdatePackagesWidget (RKLoadLibsDialog *dialog);
-
- ~UpdatePackagesWidget ();
-public slots:
- void updateSelectedButtonClicked ();
- void updateAllButtonClicked ();
- void getListButtonClicked ();
- void ok ();
- void cancel ();
-protected:
- void rCommandDone (RCommand *command);
+ void initialize (RCommandChain *chain);
+
+ enum Columns {
+ EnhancesRKWard,
+ InstallationStatus,
+ PackageName,
+ PackageTitle,
+ Version,
+ Location,
+ COLUMN_COUNT
+ };
+ enum ToplevelItems {
+ UpdateablePackages,
+ NewPackages,
+ InstalledPackages,
+ TOPLEVELITEM_COUNT
+ };
+ enum PackageStatusChange {
+ Install,
+ Remove,
+ NoAction
+ };
+
+/* Item model implementation */
+ int rowCount (const QModelIndex &parent = QModelIndex()) const;
+ int columnCount (const QModelIndex &) const { return COLUMN_COUNT; };
+ QVariant data (const QModelIndex &index, int role=Qt::DisplayRole) const;
+ QVariant headerData (int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const;
+ Qt::ItemFlags flags (const QModelIndex &index) const;
+ QModelIndex index (int row, int column, const QModelIndex &parent=QModelIndex()) const;
+ QModelIndex parent (const QModelIndex &index) const;
+ bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+/** returns a list of packages selected for installation / update */
+ QStringList packagesToInstall () const;
+/** fills a list of packages selected for removal, and a parallel list of the locations, from which to remove.
+ * @return true, if any packages are marked for removal, false otherwise. */
+ bool packagesToRemove (QStringList *packages, QStringList *liblocs);
+/** 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);
+/** reset all installation states to NoAction */
+ void clearStatus ();
+ QStringList currentRepositories () const { return current_repos; };
+private slots:
+ void statusCommandFinished (RCommand *command);
private:
- void updatePackages (const QStringList &list);
- QTreeWidget *updateable_view;
+ QStringList available_packages, available_titles, available_versions, available_repos;
+ QStringList installed_packages, installed_titles, installed_versions, installed_libpaths;
+ RData::IntStorage enhance_rk_in_available;
+ RData::IntStorage enhance_rk_in_installed;
+ RData::IntStorage new_packages_in_available;
+ RData::IntStorage updateable_packages_in_available;
+ RData::IntStorage updateable_packages_in_installed;
+ QVector<PackageStatusChange> installed_status;
+ QVector<PackageStatusChange> available_status;
+ QVector<bool> installed_has_update;
- QPushButton *update_selected_button;
- QPushButton *update_all_button;
- QPushButton *get_list_button;
- PackageInstallParamsWidget *install_params;
-
- RKLoadLibsDialog *parent;
+ QStringList current_repos;
};
/**
-Allows the user to install further R packages. For now only packages from CRAN.
-Ro be used in RKLoadLibsDialog.
+Allows the user to update / install R packages.
+To be used in RKLoadLibsDialog.
@author Thomas Friedrichsmeier
*/
-class InstallPackagesWidget : public QWidget, public RCommandReceiver {
+class InstallPackagesWidget : public QWidget {
Q_OBJECT
public:
InstallPackagesWidget (RKLoadLibsDialog *dialog);
@@ -183,17 +218,16 @@
~InstallPackagesWidget ();
void trySelectPackage (const QString &package_name);
public slots:
- void installSelectedButtonClicked ();
void getListButtonClicked ();
void ok ();
+ void apply ();
void cancel ();
-protected:
- void rCommandDone (RCommand *command);
private:
void installPackages (const QStringList &list);
- QTreeWidget *installable_view;
+ QTreeView *packages_view;
+ RKRPackageInstallationStatus *packages_status;
+ QSortFilterProxyModel *model;
- QPushButton *install_selected_button;
QPushButton *get_list_button;
PackageInstallParamsWidget *install_params;
Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R 2011-09-23 14:00:03 UTC (rev 3821)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/R/internal.R 2011-09-23 17:41:55 UTC (rev 3822)
@@ -90,6 +90,29 @@
return(pluginmaps)
}
+# Gather status information on installed and available packages.
+# Return value is used in class RKRPackageInstallationStatus of the frontend
+".rk.get.package.intallation.state" <- function () {
+ # fetch all status information
+ available <- .rk.cached.available.packages ()
+ inst <- installed.packages (fields="Title")
+ old <- as.data.frame (old.packages (available=available), stringsAsFactors=FALSE)
+ new <- new.packages (instPkgs=inst, available=available)
+
+ # convert info to a more suitable format
+ available <- as.data.frame (available, stringsAsFactors=FALSE)
+ inst <- as.data.frame (inst, stringsAsFactors=FALSE)
+ oldinst <- match (paste (old$Package, old$LibPath), paste (inst$Package, inst$LibPath)) # convert package names to position with in the installed packages info
+ oldavail <- match (old$Package, available$Package) # convert package names to position with in the available packages info
+ new <- match (new, available$Package) # same for new packages
+
+ list ("available" = list (available$Package, available$Title, available$Version, available$Repository, grepl ("rkward", available$Enhances)),
+ "installed" = list (inst$Package, inst$Title, inst$Version, inst$LibPath, grepl ("rkward", inst$Enhances)),
+ "new" = as.integer (new - 1),
+ "old" = list (as.integer (oldinst - 1), as.integer (oldavail - 1)),
+ "repos" = as.character (options("repos")$repos))
+}
+
# package information formats may - according to the help - be subject to change. Hence this function to cope with "missing" values
# also it concatenates everything to a single vector, so we can easily get the whole structure with a single call
".rk.get.installed.packages" <- function () {
@@ -123,16 +146,6 @@
return (x)
}
-".rk.get.old.packages" <- function () {
- x <- old.packages (available=.rk.cached.available.packages ())
- return (list (as.character (x[,"Package"]), as.character (x[,"LibPath"]), as.character (x[,"Installed"]), as.character (x[,"ReposVer"]), rk.make.repos.string ()))
-}
-
-".rk.get.available.packages" <- function () {
- x <- .rk.cached.available.packages ()
- return (list (as.character (x[,1]), as.character (x[,2]), rk.make.repos.string ()))
-}
-
"require" <- function (package, quietly = FALSE, character.only = FALSE, ...)
{
if (!character.only) {
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