All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
PluginManagerDialog.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/plugins/manager/PluginManagerDialog.cpp
22 
23  \brief A Qt dialog for plugin management.
24 */
25 
26 // TerraLib
27 #include "../../utils/CentralizedCheckBoxDelegate.h"
28 #include "../../utils/ResourceChooser.h"
29 #include "../../../../plugin/AbstractPlugin.h"
30 #include "../../../../plugin/PluginInfo.h"
31 #include "../../../../plugin/PluginManager.h"
32 #include "../../../../plugin/Utils.h"
33 #include "../../help/HelpManager.h"
34 #include "../../Exception.h"
35 #include "PluginManagerDialog.h"
36 #include "PluginsModel.h"
37 #include "ui_PluginManagerDialogForm.h"
38 
39 // STL
40 #include <algorithm>
41 
42 // Qt
43 #include <QtCore/QDir>
44 #include <QtCore/QFileInfo>
45 #include <QtCore/QUrl>
46 #include <QMessageBox>
47 #include <QPixmap>
48 #include <QtNetwork/QNetworkAccessManager>
49 #include <QtNetwork/QNetworkReply>
50 #include <QtNetwork/QNetworkRequest>
51 
52 bool PluginExists(const std::string& pluginName)
53 {
54  try
55  {
56  te::plugin::PluginManager::getInstance().getPlugin(pluginName);
57  return true;
58  }
59  catch(te::plugin::Exception&)
60  {
61  return false;
62  }
63 }
64 
65 void CheckLoadedDependencies(te::plugin::PluginInfo* plg, std::vector<std::string>& deps)
66 {
67  deps.clear();
68 
69  std::vector<std::string> plgs = te::plugin::PluginManager::getInstance().getDependents(plg->m_name);
70  std::vector<std::string>::iterator it;
71 
72  for(it=plgs.begin(); it!=plgs.end(); ++it)
73  {
74  std::string plgName = *it;
75 
76  if(te::plugin::PluginManager::getInstance().isLoaded(plgName))
77  deps.push_back(plgName);
78  }
79 }
80 
81 void CheckRequiredDependencies(te::plugin::PluginInfo* plg, std::vector<std::string>& deps)
82 {
83  deps.clear();
84 
85  std::vector<std::string> plgs = plg->m_requiredPlugins;
86  std::vector<std::string>::iterator it;
87 
88  for(it=plgs.begin(); it!=plgs.end(); ++it)
89  {
90  std::string plgName = *it;
91 
92  if(!PluginExists(plgName))
93  {
94  QString msg("Unable to load <b>%1</b>. Dependency missed: <ul><li><b>%2</b></li></ul>.");
95  msg = msg.arg(plg->m_name.c_str(), plgName.c_str());
96 
97  throw te::qt::widgets::Exception(msg.toStdString());
98  }
99 
100  if(!te::plugin::PluginManager::getInstance().isLoaded(plgName))
101  deps.push_back(plgName);
102  }
103 }
104 
105 QString GetPluginDepsMessage(const std::string& plg, const std::vector<std::string>& dps)
106 {
107  QString result;
108 
109  if(!dps.empty())
110  {
111  std::vector<std::string>::const_iterator it;
112 
113  result = QObject::tr("Unloading <b>%1</b> will also unload the plugins: <ul>");
114  result = result.arg(plg.c_str());
115 
116  for(it=dps.begin(); it!=dps.end(); ++it)
117  {
118  result += QString("<li><b>%1</b></li>");
119  result = result.arg((*it).c_str());
120  }
121 
122  result += QObject::tr("</ul> Did you want to continue?");
123  }
124 
125  return result;
126 }
127 
128 QString GetPluginReqsMessage(const std::string& plg, const std::vector<std::string>& dps)
129 {
130  QString result;
131 
132  if(!dps.empty())
133  {
134  std::vector<std::string>::const_iterator it;
135 
136  result = QObject::tr("In order to be able to load <b>%1</b> plugin, the following plugins must also be enabled: <ul>");
137  result = result.arg(plg.c_str());
138 
139  for(it=dps.begin(); it!=dps.end(); ++it)
140  {
141  result += QString("<li><b>%1</b></li>");
142  result = result.arg((*it).c_str());
143  }
144 
145  result += QObject::tr("</ul> Allow them to be anabled?");
146  }
147 
148  return result;
149 }
150 
151 void MakeRemove(const std::vector<te::plugin::PluginInfo*>& plgs, const std::vector<te::qt::widgets::PluginsModel::PluginsStatus>& status, QWidget* parent)
152 {
153  std::vector<std::string> dps;
154 
155  for(size_t i=0; i<status.size(); i++)
156  if(status[i].testFlag(te::qt::widgets::PluginsModel::To_remove) && PluginExists(plgs[i]->m_name))
157  {
158  CheckLoadedDependencies(plgs[i], dps);
159 
160  if(!dps.empty())
161  {
162  QString msg = GetPluginDepsMessage(plgs[i]->m_name, dps);
163  if(QMessageBox::question(parent, QObject::tr("Remove plugins"), msg, QMessageBox::No, QMessageBox::Yes) == QMessageBox::No)
164  continue;
165  }
166 
167  te::plugin::PluginManager::getInstance().remove(plgs[i]->m_name);
168  }
169 }
170 
171 void MakeDisable(const std::vector<te::plugin::PluginInfo*>& plgs, const std::vector<te::qt::widgets::PluginsModel::PluginsStatus>& status, QWidget* parent)
172 {
173  std::vector<std::string> dps;
174 
175  for(size_t i=0; i<status.size(); i++)
176  if(status[i].testFlag(te::qt::widgets::PluginsModel::To_disable) && te::plugin::PluginManager::getInstance().isLoaded(plgs[i]->m_name))
177  {
178  CheckLoadedDependencies(plgs[i], dps);
179 
180  if(!dps.empty())
181  {
182  QString msg = GetPluginDepsMessage(plgs[i]->m_name, dps);
183  if(QMessageBox::question(parent, QObject::tr("Unload plugins"), msg, QMessageBox::No, QMessageBox::Yes) == QMessageBox::No)
184  continue;
185  }
186 
187  te::plugin::PluginManager::getInstance().unload(plgs[i]->m_name);
188  }
189 }
190 
191 void MakeAdd(const std::vector<te::plugin::PluginInfo*>& plgs, const std::vector<te::qt::widgets::PluginsModel::PluginsStatus>& status)
192 {
193  for(size_t i=0; i<status.size(); i++)
194  if(status[i].testFlag(te::qt::widgets::PluginsModel::To_add) && (!PluginExists(plgs[i]->m_name)))
196 }
197 
198 void MakeEnable(const std::vector<te::plugin::PluginInfo*>& plgs, const std::vector<te::qt::widgets::PluginsModel::PluginsStatus>& status, QWidget* parent)
199 {
200  std::vector<std::string> dps;
201  std::vector<std::string>::iterator it;
202 
203  for(size_t i=0; i<status.size(); i++)
204  {
205  try
206  {
207  if(status[i].testFlag(te::qt::widgets::PluginsModel::To_enable) && te::plugin::PluginManager::getInstance().isUnloadedPlugin(plgs[i]->m_name))
208  {
209  CheckRequiredDependencies(plgs[i], dps);
210 
211  if(!dps.empty())
212  {
213  QString msg = GetPluginReqsMessage(plgs[i]->m_name, dps);
214 
215  if(QMessageBox::question(parent, QObject::tr("Enable plugin"), msg, QMessageBox::No, QMessageBox::Yes) == QMessageBox::No)
216  continue;
217 
218  for(it=dps.begin(); it!=dps.end(); ++it)
220  }
221 
222  te::plugin::PluginManager::getInstance().load(plgs[i]->m_name);
223  }
224  }
225  catch(const std::exception& e)
226  {
227  QMessageBox::warning(parent, QObject::tr("Fail to load plugin"), e.what());
228 
229  continue;
230  }
231  }
232 }
233 
234 void AddPlugin(const QString& fileName, te::qt::widgets::PluginsModel* model)
235 {
236  te::plugin::PluginInfo* pInfo = te::plugin::GetInstalledPlugin(QDir::toNativeSeparators(fileName).toStdString());
237 
238  if(PluginExists(pInfo->m_name))
239  return;
240 
242 
243  delete pInfo;
244 }
245 
247 {
248  int rows = model->rowCount(QModelIndex());
249  int st = model->index(0,0).data(Qt::CheckStateRole).toInt();
250 
251  for(int i=1; i<rows; i++)
252  {
253  int st2 = model->index(i,0).data(Qt::CheckStateRole).toInt();
254 
255  if(st2 != st)
256  return Qt::PartiallyChecked;
257  }
258 
259  return (Qt::CheckState) st;
260 }
261 
263  : QDialog(parent, f),
264  m_ui(new Ui::PluginManagerDialogForm)
265 {
266  m_ui->setupUi(this);
267 
268  setWindowTitle(tr("Manage Application Plugins"));
269 
270  m_model = new PluginsModel(this);
271  m_ui->m_installedPluginsTableWidget->setModel(m_model);
272  m_ui->m_installedPluginsTableWidget->setItemDelegate(new CentralizedCheckBoxDelegate(this));
273 
275  filliPlugins();
276 
277  connect(m_ui->m_applyPushButton, SIGNAL(pressed()), this, SLOT(applyPushButtonPressed()));
278  connect(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SLOT(dataChanged(const QModelIndex&, const QModelIndex&)));
279 // connect(m_ui->m_helpPushButton, SIGNAL(pressed()), SLOT(onHelpPushButtonPressed()));
280  connect(m_ui->m_enableAll, SIGNAL(clicked(bool)), SLOT(onEnableAllChanged(bool)));
281 
282  m_ui->m_addButton->setIcon(QIcon::fromTheme("list-add"));
283  m_ui->m_removeButton->setIcon(QIcon::fromTheme("list-remove"));
284 
285  m_ui->m_installedPluginsTableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
286 
287  m_ui->m_pluginsTabWidget->setTabEnabled(1, false);
288 
289  m_ui->m_enableAll->setCheckState(GetCheckState(m_model));
290 
291  m_ui->m_helpPushButton->setPageReference("widgets/pluginmanager/PluginManager.html");
292 }
293 
295 {
296 }
297 
299 {
300  std::vector<te::plugin::PluginInfo*> plgs;
301  std::vector<te::qt::widgets::PluginsModel::PluginsStatus> status;
302 
303  m_model->getPluginsInfo(plgs, status);
304 
305  MakeRemove(plgs, status, this);
306  MakeDisable(plgs, status, this);
307  MakeAdd(plgs, status);
308  MakeEnable(plgs, status, this);
309 
310  m_model->clear();
311 
312  fillInstalledPlugins();
313 
314  m_ui->m_applyPushButton->setEnabled(false);
315 }
316 
318 {
319  //if((item == 0) || (item->column() != 0))
320  // return;
321 
322  //if(item->tableWidget() == m_ui->m_installedPluginsTableWidget)
323  // m_changedInstalledPlugins.insert(item->row());
324  //else if(item->tableWidget() == m_ui->m_netPluginsTableWidget)
325  // m_downloadPlugins.insert(item->row());
326 
327  //if(m_ui->m_installedPluginsTableWidget->item(item->row(), 0)->flags() & Qt::ItemIsUserCheckable)
328  // m_ui->m_applyPushButton->setEnabled(true);
329 }
330 
332 {
333  //if(reply->error() != QNetworkReply::NoError)
334  //{
335  // QMessageBox::warning(this,
336  // tr("TerraLib Qt Components"),
337  // tr("Could not retrieve available plugins from the Internet!"));
338 
339  // return;
340  //}
341 
342  //QVariant contenttype = reply->header(QNetworkRequest::ContentTypeHeader);
343 
344  //if(!contenttype.isValid())
345  //{
346  // QMessageBox::warning(this,
347  // tr("TerraLib Qt Components"),
348  // tr("Plugins list missing content type!"));
349 
350  // return;
351  //}
352 
353  //if(contenttype.toString() != QString("application/json"))
354  //{
355  // QString errmsg(tr("Available plugins from Internet provided with wrong content type: %s!"));
356  // errmsg.arg(0, contenttype.toString());
357 
358  // QMessageBox::warning(this,
359  // tr("TerraLib Qt Components"),
360  // errmsg);
361 
362  // return;
363  //}
364 
365  //QByteArray data = reply->readAll();
366 
367  //if(data.isEmpty())
368  //{
369  // QMessageBox::warning(this,
370  // tr("TerraLib Qt Components"),
371  // tr("The plugin list from the Internet is empty!"));
372 
373  // return;
374  //}
375 
376  //m_iplugins.clear();
377 
378  //ReadPluginInfo(data, m_iplugins);
379 
380  //int nrows = static_cast<int>(m_iplugins.size());
381 
382  //m_ui->m_netPluginsTableWidget->setRowCount(nrows);
383 
384  //std::set<iPluginInfo>::const_iterator it = m_iplugins.begin();
385  //std::set<iPluginInfo>::const_iterator itend = m_iplugins.end();
386 
387  //int i = 0;
388 
389  //while(it != itend)
390  //{
391  // te::plugin::PluginInfo plugin = Convert(*it);
392  // addEntry(i, plugin, false, m_ui->m_netPluginsTableWidget);
393 
394  // ++it;
395  // ++i;
396  //}
397 
398  //m_ui->m_netPluginsTableWidget->resizeColumnsToContents();
399  //m_ui->m_netPluginsTableWidget->sortByColumn(1, Qt::AscendingOrder);
400 }
401 
403 {
404  QString rsc = ResourceChooser::getResource(qApp->applicationDirPath(), tr("TerraLib Plug-in Files (*.teplg *.TEPLG)"), this);
405 
406  try
407  {
408  if(rsc.isEmpty())
409  return;
410 
411  QFileInfo info(rsc);
412 
413  if(info.isFile())
414  AddPlugin(info.absoluteFilePath(), m_model);
415  else
416  {
417  if(!info.isDir())
418  throw tr("There's no resource selected, no plugins found.");
419 
420  QStringList filters;
421  filters <<"*.teplg" <<"*.TEPLG";
422 
423  QDir dir(info.canonicalFilePath());
424 
425  QString qdir_s = dir.absolutePath();
426 
427  QStringList plgs = dir.entryList(filters, QDir::Files);
428 
429  if(plgs.isEmpty())
430  throw tr("There's no plugins found.");
431 
432  QStringList::iterator it;
433 
434  for(it = plgs.begin(); it != plgs.end(); ++it)
435  AddPlugin(QDir::toNativeSeparators(dir.absoluteFilePath(*it)), m_model);
436  }
437 
438  m_ui->m_applyPushButton->setEnabled(true);
439  }
440  catch(QString& exc)
441  {
442  QMessageBox msg;
443  msg.setWindowTitle(tr("Fail to load plugin files"));
444  msg.setIcon(QMessageBox::Warning);
445  msg.setText(exc);
446  msg.exec();
447  }
448  catch(te::plugin::Exception& exc)
449  {
450  QMessageBox msg;
451  msg.setWindowTitle(tr("Fail to load plugin files"));
452  msg.setIcon(QMessageBox::Warning);
453  msg.setText(exc.what());
454  msg.exec();
455  }
456 }
457 
459 {
460  QModelIndexList lst = m_ui->m_installedPluginsTableWidget->selectionModel()->selectedRows(0);
461 
462  if(lst.isEmpty())
463  {
464  QMessageBox q(this);
465 
466  q.setIcon(QMessageBox::Warning);
467  q.setWindowTitle(tr("Remove installed plugins"));
468  q.setText(tr("There are NOT selected plugins."));
469  q.exec();
470 
471  return;
472  }
473 
474  m_model->removePlugins(lst);
475 
476  m_ui->m_applyPushButton->setEnabled(true);
477 }
478 
479 void te::qt::widgets::PluginManagerDialog::dataChanged(const QModelIndex& index, const QModelIndex&)
480 {
481  m_ui->m_applyPushButton->setEnabled(true);
482  m_ui->m_enableAll->setCheckState(GetCheckState(m_model));
483 }
484 
485 //void te::qt::widgets::PluginManagerDialog::onHelpPushButtonPressed()
486 //{
487 // te::qt::widgets::HelpManager::getInstance().showHelp("widgets/pluginmanager/PluginManager.html", "dpi.inpe.br.qtwidgets");
488 //}
489 
491 {
492  Qt::CheckState state = (st) ? Qt::Checked : Qt::Unchecked;
493 
494  m_ui->m_enableAll->setCheckState(state);
495  {
496  int nrows = m_model->rowCount(QModelIndex());
497 
498  for(int i=0; i<nrows; i++)
499  {
500  QModelIndex idx = m_model->index(i, 0);
501  m_model->setData(idx, QVariant(state), Qt::CheckStateRole);
502  }
503  }
504 
505  m_ui->m_enableAll->setCheckState(GetCheckState(m_model));
506 }
507 
509 {
511 
512  std::vector<std::string> plugins = pm.getPlugins();
513 
514  int nrows = static_cast<int>(plugins.size());
515 
516  for(int i = 0; i < nrows; ++i)
517  {
518  const te::plugin::PluginInfo& plugin = pm.getPlugin(plugins[i]);
519  addEntry(i, plugin, pm.isLoaded(plugin.m_name));
520  }
521 
522  m_ui->m_installedPluginsTableWidget->resizeColumnsToContents();
523  m_ui->m_installedPluginsTableWidget->sortByColumn(1, Qt::AscendingOrder);
524 }
525 
527 {
528  //m_ui->m_netPluginsTableWidget->clearContents();
529  //m_ui->m_netPluginsTableWidget->verticalHeader()->hide();
530  //m_ui->m_netPluginsTableWidget->hideColumn(9);
531 
532 
533  //QNetworkAccessManager* manager = new QNetworkAccessManager(this);
534 
535  //connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
536 
537  //manager->get(QNetworkRequest(QUrl("http://www.dpi.inpe.br/~gribeiro/terralib5/plugins/win32/plugins.json")));
538 }
539 
541 {
542  bool bk = te::plugin::PluginManager::getInstance().isBrokenPlugin(pinfo.m_name);
543  te::qt::widgets::PluginsModel::PluginsStatus st;
544 
545  if(bk)
547  else
548  {
549  if(checked)
551  else
553  }
554 
555  m_model->addPlugin(&pinfo, st);
556 }
557 
std::string m_name
The plugin name: an internal value used to identify the plugin in the system. Must be a unique value...
Definition: PluginInfo.h:66
int rowCount(const QModelIndex &parent) const
Returns the number of plugins regitered in plugins manager.
std::vector< std::string > m_requiredPlugins
The list of required plugins in order to lunch the plugin.
Definition: PluginInfo.h:78
void addPlugin(const te::plugin::PluginInfo *info, const PluginsStatus &status)
Adds information about plugin.
void CheckRequiredDependencies(te::plugin::PluginInfo *plg, std::vector< std::string > &deps)
void MakeRemove(const std::vector< te::plugin::PluginInfo * > &plgs, const std::vector< te::qt::widgets::PluginsModel::PluginsStatus > &status, QWidget *parent)
PluginManagerDialog(QWidget *parent=0, Qt::WindowFlags f=0)
A singleton for managing plugins.
Definition: PluginManager.h:61
void addEntry(int i, const te::plugin::PluginInfo &pinfo, bool checked)
Qt::CheckState GetCheckState(te::qt::widgets::PluginsModel *model)
static PluginManager & getInstance()
It returns a reference to the singleton instance.
Plugin haas missed dependencies.
Definition: PluginsModel.h:66
std::vector< std::string > getPlugins() const
It returns the list of plugins managed by PluginManager.
void dataChanged(const QModelIndex &, const QModelIndex &)
static QString getResource(const QString &initialPath, const QString &filter, QWidget *parent=0)
use the static when the ResourceChooser have to be presented as a Dialog.
void tableWidgetClicked(QTableWidgetItem *item)
void CheckLoadedDependencies(te::plugin::PluginInfo *plg, std::vector< std::string > &deps)
void MakeEnable(const std::vector< te::plugin::PluginInfo * > &plgs, const std::vector< te::qt::widgets::PluginsModel::PluginsStatus > &status, QWidget *parent)
QString GetPluginDepsMessage(const std::string &plg, const std::vector< std::string > &dps)
void MakeAdd(const std::vector< te::plugin::PluginInfo * > &plgs, const std::vector< te::qt::widgets::PluginsModel::PluginsStatus > &status)
bool PluginExists(const std::string &pluginName)
const PluginInfo & getPlugin(const std::string &name) const
It returns the plugin identified by the given name.
QVariant data(const QModelIndex &index, int role) const
Returns data identified by index.
bool isLoaded(const std::string &pname) const
It returns true if the plugin is loaded otherwise returns false.
QString GetPluginReqsMessage(const std::string &plg, const std::vector< std::string > &dps)
A Qt dialog for plugin management.
The basic information about a plugin.
Definition: PluginInfo.h:61
void MakeDisable(const std::vector< te::plugin::PluginInfo * > &plgs, const std::vector< te::qt::widgets::PluginsModel::PluginsStatus > &status, QWidget *parent)
void AddPlugin(const QString &fileName, te::qt::widgets::PluginsModel *model)
TEPLUGINEXPORT PluginInfo * GetInstalledPlugin(const std::string &pluginFilePath)
It returns information about a given plugin provided its plugin configuration file name or dir...
Definition: Utils.cpp:80
std::auto_ptr< Ui::PluginManagerDialogForm > m_ui