1 /***************************************************************************
2                           rkloadlibsdialog  -  description
3                              -------------------
4     begin                : Mon Sep 6 2004
5     copyright            : (C) 2004 - 2015 by Thomas Friedrichsmeier
6     email                : thomas.friedrichsmeier@kdemail.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 #ifndef RKLOADLIBSDIALOG_H
18 #define RKLOADLIBSDIALOG_H
19 
20 #include <kpagedialog.h>
21 
22 #include <qstringlist.h>
23 #include <QProcess>
24 #include <QSortFilterProxyModel>
25 
26 #include "../settings/rksettingsmoduler.h"
27 #include "../rbackend/rcommandreceiver.h"
28 
29 class QLineEdit;
30 class QTreeView;
31 class QTreeWidget;
32 class QSortFilterProxyModel;
33 class QComboBox;
34 class QPushButton;
35 class RKProgressControl;
36 class QWidget;
37 class QCloseEvent;
38 class RCommandChain;
39 class QCheckBox;
40 class PackageInstallParamsWidget;
41 class InstallPackagesWidget;
42 class RKDynamicSearchLine;
43 
44 /**
45 Dialog which excapsulates widgets to load/unload, update and install R packages
46 
47 @author Thomas Friedrichsmeier
48 */
49 
50 // TODO: add a static member to create (single) instance of the dialog
51 
52 class RKLoadLibsDialog : public KPageDialog, public RCommandReceiver {
53 Q_OBJECT
54 public:
55 	RKLoadLibsDialog (QWidget *parent, RCommandChain *chain, bool modal=false);
56 
57 	~RKLoadLibsDialog ();
58 
59 	bool installPackages (const QStringList &packages, QString to_libloc, bool install_suggested_packages, const QStringList& repos);
60 	bool removePackages (QStringList packages, QStringList from_liblocs);
61 
62 /** opens a modal RKLoadLibsDialog with the "Install new Packages" tab on front (To be used when a require () fails in the R backend
63 @param parent parent QWidget. The dialog will be centered there
64 @param chain RCommandChain to run the necessary commands in
65 @param package_name name of the required package */
66 	static void showInstallPackagesModal (QWidget *parent, RCommandChain *chain, const QString &package_name);
67 	static void showPluginmapConfig (QWidget *parent=0, RCommandChain *chain=0);
currentLibraryLocations()68 	QStringList currentLibraryLocations ()  const { return library_locations; };
69 	void accept () override;
70 	void reject () override;
71 signals:
72 	void downloadComplete ();
73 	void installationComplete ();
74 	void libraryLocationsChanged (const QStringList &liblocs);
75 	void installationOutput (const QString &output);
76 	void installationError (const QString &error);
77 	void installedPackagesChanged ();
78 protected:
79 	void rCommandDone (RCommand *command) override;
80 	void closeEvent (QCloseEvent *e) override;
81 protected slots:
82 	void childDeleted ();
83 	void processExited (int exitCode, QProcess::ExitStatus exitStatus);
84 	void installationProcessOutput ();
85 	void installationProcessError ();
86 	void automatedInstall ();
87 	void slotPageChanged ();
88 private:
89 	void addLibraryLocation (const QString &new_loc);
90 	void tryDestruct ();
91 	void runInstallationCommand (const QString& command, bool as_root, const QString& message, const QString& title);
92 	KPageWidgetItem* addChild (QWidget *child_page, const QString &caption);
93 friend class LoadUnloadWidget;
94 friend class InstallPackagesWidget;
95 	RCommandChain *chain;
96 
97 	InstallPackagesWidget *install_packages_widget;	// needed for automated installation
98 	KPageWidgetItem *install_packages_pageitem;
99 	KPageWidgetItem *configure_pluginmaps_pageitem;
100 
101 	QStringList library_locations;
102 
103 	QString auto_install_package;
104 	int num_child_widgets;
105 	bool was_accepted;
106 
107 	QProcess* installation_process;
108 };
109 
110 /**
111 Shows which packages are available (installed) / loaded, and lets the user load or detach packages.
112 To be used in RKLoadLibsDialog
113 
114 @author Thomas Friedrichsmeier
115 */
116 class LoadUnloadWidget : public QWidget, public RCommandReceiver {
117 Q_OBJECT
118 public:
119 	explicit LoadUnloadWidget (RKLoadLibsDialog *dialog);
120 
121 	~LoadUnloadWidget ();
122 signals:
123 	void loadUnloadDone ();
124 public slots:
125 	void loadButtonClicked ();
126 	void detachButtonClicked ();
127 	void ok ();
128 	void apply ();
129 	void cancel ();
130 	void updateInstalledPackages ();
131 	void updateButtons ();
132 	void activated ();
133 protected:
134 	void rCommandDone (RCommand *command) override;
135 private:
136 	void updateCurrentList ();
137 	void doLoadUnload ();
138 
139 	QTreeWidget *loaded_view;
140 	QTreeWidget *installed_view;
141 
142 	QPushButton *load_button;
143 	QPushButton *detach_button;
144 
145 	QStringList prev_packages;
146 
147 	RKLoadLibsDialog *parent;
148 };
149 
150 /** Item model and encapsulation for package status (used in InstallPackagesWidget) */
151 class RKRPackageInstallationStatus : public QAbstractItemModel {
152 	Q_OBJECT
153 public:
154 	explicit RKRPackageInstallationStatus (QObject* parent);
155 	~RKRPackageInstallationStatus ();
156 
157 	void initialize (RCommandChain *chain);
158 
159 	enum Columns {
160 		EnhancesRKWard,
161 		InstallationStatus,
162 		PackageName,
163 		PackageTitle,
164 		Version,
165 		Location,
166 		COLUMN_COUNT
167 	};
168 	enum ToplevelItems {
169 		UpdateablePackages,
170 		NewPackages,
171 		InstalledPackages,
172 		TOPLEVELITEM_COUNT
173 	};
174 	enum PackageStatusChange {
175 		Install,
176 		Remove,
177 		NoAction
178 	};
179 
180 /* Item model implementation */
181 	int rowCount (const QModelIndex &parent = QModelIndex()) const override;
columnCount(const QModelIndex &)182 	int columnCount (const QModelIndex &) const override { return COLUMN_COUNT; };
183 	QVariant data (const QModelIndex &index, int role=Qt::DisplayRole) const override;
184 	QVariant headerData (int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override;
185 	Qt::ItemFlags flags (const QModelIndex &index) const override;
186 	QModelIndex index (int row, int column, const QModelIndex &parent=QModelIndex()) const override;
187 	QModelIndex parent (const QModelIndex &index) const override;
188 	bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
189 
190 /** returns a list of packages selected for installation / update */
191 	QStringList packagesToInstall () const;
192 /** fills a list of packages selected for removal, and a parallel list of the locations, from which to remove.
193  * @return true, if any packages are marked for removal, false otherwise. */
194 	bool packagesToRemove (QStringList *packages, QStringList *liblocs);
195 /** mark a package for installation.
196  * @returns the index of the package, if the package is available, an invalid index, if it is not available */
197 	QModelIndex markPackageForInstallation (const QString& package_name);
198 /** mark all available updates for installation.
199  * @returns the index of the "Updateable Packages" item */
200 	QModelIndex markAllUpdatesForInstallation ();
201 /** reset all installation states to NoAction */
202 	void clearStatus ();
currentRepositories()203 	QStringList currentRepositories () const { return current_repos; };
initialized()204 	bool initialized () const { return _initialized; };
205 private slots:
206 	void statusCommandFinished (RCommand *command);
207 private:
208 	QStringList available_packages, available_titles, available_versions, available_repos;
209 	QStringList installed_packages, installed_titles, installed_versions, installed_libpaths;
210 	RData::IntStorage enhance_rk_in_available;
211 	RData::IntStorage enhance_rk_in_installed;
212 	RData::IntStorage new_packages_in_available;
213 	RData::IntStorage updateable_packages_in_available;
214 	RData::IntStorage updateable_packages_in_installed;
215 	QVector<PackageStatusChange> installed_status;
216 	QVector<PackageStatusChange> available_status;
217 	QVector<bool> installed_has_update;
218 	bool _initialized;
219 
220 	QStringList current_repos;
221 };
222 
223 class RKRPackageInstallationStatusSortFilterModel : public QSortFilterProxyModel {
224 public:
225 	explicit RKRPackageInstallationStatusSortFilterModel (QObject* parent = 0);
226 	~RKRPackageInstallationStatusSortFilterModel ();
227 	void setRKWardOnly (bool only);
228 protected:
229 	bool lessThan (const QModelIndex &left, const QModelIndex &right) const override;
230 	bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const override;
231 	bool rkward_only;
232 };
233 
234 /**
235 Allows the user to update / install R packages.
236 To be used in RKLoadLibsDialog.
237 
238 @author Thomas Friedrichsmeier
239 */
240 class InstallPackagesWidget : public QWidget {
241 Q_OBJECT
242 public:
243 	explicit InstallPackagesWidget (RKLoadLibsDialog *dialog);
244 
245 	~InstallPackagesWidget ();
246 	void trySelectPackage (const QString &package_name);
247 	void initialize ();
248 public slots:
249 	void ok ();
250 	void apply ();
251 	void cancel ();
252 	void filterChanged ();
253 	void activated ();
254 	void markAllUpdates ();
255 	void configureRepositories ();
256 	void rowClicked (const QModelIndex& row);
257 private:
258 	void doInstall (bool refresh);
259 	QTreeView *packages_view;
260 	RKRPackageInstallationStatus *packages_status;
261 	RKRPackageInstallationStatusSortFilterModel *model;
262 
263 	QPushButton *mark_all_updates_button;
264 	RKDynamicSearchLine *filter_edit;
265 	QCheckBox *rkward_packages_only;
266 	PackageInstallParamsWidget *install_params;
267 
268 	RKLoadLibsDialog *parent;
269 };
270 
271 /**
272 Simple helper class for RKLoadLibsDialog to allow selection of installation parameters
273 
274 @author Thomas Friedrichsmeier
275 */
276 class PackageInstallParamsWidget : public QWidget {
277 Q_OBJECT
278 public:
279 	explicit PackageInstallParamsWidget (QWidget *parent);
280 
281 	~PackageInstallParamsWidget ();
282 
283 	bool installSuggestedPackages ();
284 	QString installLocation ();
285 public slots:
286 	void liblocsChanged (const QStringList &newlist);
287 private:
288 	QComboBox *libloc_selector;
289 	QCheckBox *suggested_packages;
290 };
291 
292 
293 #include "../settings/rksettingsmoduleplugins.h"
294 
295 class RKPluginMapSelectionWidget : public QWidget {
296 Q_OBJECT
297 public:
298 	explicit RKPluginMapSelectionWidget (RKLoadLibsDialog *dialog);
299 	virtual ~RKPluginMapSelectionWidget ();
300 public slots:
301 	void ok ();
302 	void apply ();
303 	void cancel ();
304 	void activated ();
changed()305 	void changed () { changes_pending = true; };
306 private:
307 	RKMultiStringSelectorV2* selector;
308 	RKSettingsModulePluginsModel* model;
309 	bool changes_pending;
310 };
311 
312 #endif
313