ATLAS Offline Software
Loading...
Searching...
No Matches
VP1ChannelManager.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6// //
7// Implementation of class VP1ChannelManager //
8// //
9// Author: Thomas Kittelmann <Thomas.Kittelmann@cern.ch> //
10// //
11// Initial version: April 2007 //
12// //
14
16//
17// NB: It is assumed that all channel methods are very fast to execute. Real work belongs in systems!!
18//
19// Constructor: Allocate systems, and call registerSystem on
20// them. After the constructor the name(), information() and type()
21// methods should work (and their returned values should not change
22// throughout the channel lifetime. You may never delete a system yourself.
23//
24// Create: You can assume that all systems have had their create()
25// method already called. Here you can perform any initialisation you
26// need to, including allocating a controller if you need to and
27// registering it with registerController. You may never delete a controller yourself.
28//
29// The next two methods, refresh and erase, will be called an
30// undetermined amount of times by the framework (including zero), and
31// always in the cycle: refresh-erase-refresh-erase-refresh-erase-...-refresh-erase
32//
33// Refresh: You can assume that all systems have just had their refresh
34// methods called, and thus have just processed data from a new event. Any gui
35// updates you need to perform (e.g. changing the zoom level of a viewer to
36// encompass all the items put into it by the systems) you can do here.
37//
38// Erase: You can assume that all systems have just had their erase methods called.
39// The goal here is to stop the channel from displaying any
40// event data, since we are preparing to leave an event and load
41// a new one. If we did not blank out the presented data here,
42// we might end up in a situation where different channels
43// displays data from different events at the same time! (For
44// accumulators this is of course a little different).
45//
46// Uncreate: You can assume that all systems have had their uncreate()
47// method already called. Here you can perform any release of resources you
48// need to (remember to no delete systems or the controller!).
49// Dont emit any signals during this method (or during the destructor).
50//
51// Destructor: There really should not be anything left to do here...
52//
54
58
61
62#include <QPluginLoader>
63#include <QFileInfo>
64#include <QMap>
65#include <QScrollArea>
66
67#include <map>
68#include <set>
69#include <cassert>
70
71//QT_NO_PLUGIN_CHECK
72
74
75public:
76
80
81 //Actual created channels:
82 std::map<QString,std::set<IVP1ChannelWidget*> > basename_2_channels;
83 std::map<QString,IVP1ChannelWidget*> uniquename_2_channel;
84
85 //plugin info:
86 std::map<QString,std::pair<QStringList,IVP1ChannelWidgetFactory *> > pluginfile_2_basenamesAndFactory;
87 std::map<QString,QString> basename_2_pluginfile;
88 std::map<QString,QPluginLoader*> pluginfile_2_pluginloader;
89
90 QList<QObject*> additionalOwnedObjects;//For deletion in destructor
93
94 std::map<IVP1ChannelWidget*,QWidget*> channel_2_controller;
95 QMap<QString,QString> basename2iconlocation;
96
97 //These next four should always be used to properly new, create,
98 //uncreate and delete channels and their systems. The channel is
99 //responsible for new'ing systems in its constructor, but
100 //create/uncreate/delete of systems are handled by the
101 //channelmanager. Controllers are also deleted by the channelmanager.
102 IVP1ChannelWidget * constructChannel( const QString & channelbasename, QString& err, bool init = true );
103
105};
106
107//___________________________________________________________________________________
109{
110 m_d->channelmanager=this;
111 m_d->scheduler=sched;
112 m_d->mainwindow=mw;
113}
114
115//___________________________________________________________________________________
117{
118 while(!m_d->uniquename_2_channel.empty())
119 deleteChannel(m_d->uniquename_2_channel.begin()->first);
120
121 std::map<QString,QPluginLoader*>::const_iterator it, itE = m_d->pluginfile_2_pluginloader.end();
122 for(it=m_d->pluginfile_2_pluginloader.begin();it!=itE;++it)
123 delete it->second;
124
125 for (QObject* o : m_d->additionalOwnedObjects)
126 delete o;
127 delete m_d;
128}
129
130//___________________________________________________________________________________
131//Fixme: Return error string in case of problems.
132bool VP1ChannelManager::deleteChannel(const QString & channeluniquename) {
133
134 //Find info:
135 assert(m_d->uniquename_2_channel.find(channeluniquename)!=m_d->uniquename_2_channel.end());
136 IVP1ChannelWidget * cw = m_d->uniquename_2_channel[channeluniquename];
137 QString bn = cw->name();
138 assert(m_d->basename_2_channels.find(bn)!=m_d->basename_2_channels.end());
139
140 //Remove channelwidget from maps, and delete it.
141 assert(m_d->basename_2_channels[bn].find(cw)!=m_d->basename_2_channels[bn].end());
142 m_d->basename_2_channels[bn].erase(m_d->basename_2_channels[bn].find(cw));
143 m_d->uniquename_2_channel.erase(m_d->uniquename_2_channel.find(channeluniquename));
144
145 m_d->scheduler->uncreateAndDelete(cw);//The actual uncreate()+delete might be postponed if a system is
146 //presently refreshing. But for all bookkeeping purposes it already
147 //happened!
148
150
151 //Remove controller from maps - and ensure the widget gets deleted
152 //in any case (it is a scrollarea, not the controller known by the
153 //actual channelwidget):
154 assert(m_d->channel_2_controller.find(cw)!=m_d->channel_2_controller.end());
155 m_d->channel_2_controller[cw]->deleteLater();
156 m_d->channel_2_controller.erase(m_d->channel_2_controller.find(cw));
157 assert(m_d->channel_2_controller.find(cw)==m_d->channel_2_controller.end());
158
159 //Finally, assign new cloneids to any remaining channels of the same basename:
160 //First wipe old info in uniquename_2_channel.
161 std::set<IVP1ChannelWidget*>::iterator it = m_d->basename_2_channels[bn].begin();
162 std::set<IVP1ChannelWidget*>::iterator itE = m_d->basename_2_channels[bn].end();
163 for (;it!=itE;++it) {
164 assert(m_d->uniquename_2_channel.find((*it)->unique_name())!=m_d->uniquename_2_channel.end());
165 m_d->uniquename_2_channel.erase(m_d->uniquename_2_channel.find((*it)->unique_name()));
166 }
167
168 it = m_d->basename_2_channels[bn].begin();
169 unsigned id(0);
170 for (;it!=itE;++it) {
171 (*it)->setCloneID(id++);
172 (*it)->unique_name();
173 assert(m_d->uniquename_2_channel.find((*it)->unique_name())==m_d->uniquename_2_channel.end());
174 m_d->uniquename_2_channel[(*it)->unique_name()]=(*it);
175 }
176
178 m_d->emit_basename_availableUnusedChannelListChanged();
179 return true;
180}
181
182
183//___________________________________________________________________________________
184bool VP1ChannelManager::unloadPluginFile(const QString & filename) {
185
186 VP1Msg::messageVerbose("VP1ChannelManager::unloadPluginFile()");
187
188 if (m_d->pluginfile_2_pluginloader.find(filename)==m_d->pluginfile_2_pluginloader.end())
189 return false;
190
191 assert(m_d->pluginfile_2_basenamesAndFactory.find(filename)!=m_d->pluginfile_2_basenamesAndFactory.end());
192 assert(m_d->pluginfile_2_pluginloader.find(filename)!=m_d->pluginfile_2_pluginloader.end());
193
194 //Find basenames provided by this plugin, as well as factory and pluginloader:
195 QStringList bns = channelsInPluginFile(filename);
196 IVP1ChannelWidgetFactory * fact = m_d->pluginfile_2_basenamesAndFactory.find(filename)->second.second;
197 QPluginLoader* loader = m_d->pluginfile_2_pluginloader[filename];
198
199 //Abort if any active channels are affected by this plugin:
200 for (const QString& bn : bns)
201 if (nActive(bn)>0)
202 return false;
203
204 //Delete factory:
205 delete fact;
206
207 //Unload:
208 bool success = loader->unload();
209 delete loader;
210
211 //Update maps:
212 m_d->pluginfile_2_basenamesAndFactory.erase(m_d->pluginfile_2_basenamesAndFactory.find(filename));
213 m_d->pluginfile_2_pluginloader.erase(m_d->pluginfile_2_pluginloader.find(filename));
214 for (const QString& bn : bns) {
215 m_d->basename_2_channels.erase(m_d->basename_2_channels.find(bn));
216 m_d->basename_2_pluginfile.erase(m_d->basename_2_pluginfile.find(bn));
217 }
218
219 //Emit signals regarding changes:
221 m_d->emit_basename_availableChannelListChanged();
222 m_d->emit_basename_availableUnusedChannelListChanged();
223
224 //Return:
225 return success;
226}
227
228//___________________________________________________________________________________
229QString VP1ChannelManager::loadPluginFile(const QString & filename)
230{
231
232 VP1Msg::messageVerbose("VP1ChannelManager::loadPluginFile() - filename: " + filename);
233
234 QString bn = QFileInfo(filename).fileName();
235
236 if (m_d->pluginfile_2_basenamesAndFactory.find(filename)!=m_d->pluginfile_2_basenamesAndFactory.end()) {
237 return "Error: Plugin already loaded.";
238 } else {
239
240
241 QFileInfo fi(filename);
242 if (!fi.exists())
243 return "File does not exist";
244 if (!fi.isReadable())
245 return "File is not readable";
246
247 VP1Msg::messageVerbose("plugin path: " + fi.absoluteFilePath());
248 VP1Msg::messageVerbose("app path: " + QCoreApplication::applicationDirPath());
249 VP1Msg::messageVerbose("library path: " + QLibraryInfo::location(QLibraryInfo::PluginsPath));
250
251 QString pluginAbsPath = fi.absoluteFilePath();
252
253 QPluginLoader * loader = new QPluginLoader(pluginAbsPath);//Fixme: Ensure all loaders gets unloaded on shutdown (and thus deleted)
254 m_d->pluginfile_2_pluginloader[filename]=loader;
255
256 bool loadOk = loader->load();
257
258 if (!loadOk) {
259 VP1Msg::message("ERROR! Failed to load plugin. Error message: "+loader->errorString());
260
261 VP1Msg::message("Trying to load the 'dbg' build...");
262
263 /*
264 * when running VP1 sometimes (especially from the devval release) the
265 * load of the plugin fails silently...
266 * After a long investigation, I found that the problem is in the mismatch
267 * between the compilation flag of the main Qt application
268 * and the flag of the plugin modules.
269 * For example the main application is compiled in 'dbg', while the plugins
270 * are compiled in 'opt' mode...
271 * We still understand why...
272 * In the meantime I implemented a workaround: the 'opt' flag is replaced
273 * by the 'dbg' flag when the plugin fails to load.
274 *
275 */
276 // QString build = "x86_64-slc6-gcc47-opt";
277 //QString buildB = "x86_64-slc6-gcc47-dbg";
278 //pluginAbsPath.replace(build, buildB);
279
280 pluginAbsPath.replace("opt", "dbg");
281
282 loader = new QPluginLoader(pluginAbsPath);
283 loadOk = loader->load();
284
285 if (loadOk) VP1Msg::message("Ok! 'dbg' build of the plugin successfully loaded!");
286 else VP1Msg::message("ERROR!! Also the 'dbg' build failed to load!!");
287
288 }
289
290
291 QObject *plugin = loader->instance();
292
293
294 if (!plugin) {
295
296 bool error = loader->errorString().isNull();
297
298
299 QString errStr = "ERROR!!";
300 if (error)
301 errStr = QString("Did not find any compatible plugins in file");
302 else
303 errStr = loader->errorString();
304
305
306 return errStr;
307 }
308
309
310 IVP1ChannelWidgetFactory * fact = qobject_cast<IVP1ChannelWidgetFactory *>(plugin);
311 m_d->additionalOwnedObjects << plugin;
312
313
314 if (!fact)
315 return "Did not find any channel factory in plugin file";
316
317
318 QStringList providedbasenames = fact->channelWidgetsProvided();
319
320
321 if (providedbasenames.count()==0)
322 return "Found channel factory in plugin file, but no advertised channels!";
323
324
325 m_d->pluginfile_2_basenamesAndFactory[filename] = std::pair<QStringList,IVP1ChannelWidgetFactory *>(providedbasenames,fact);
326
327
328 for (const QString& bn : providedbasenames) {
329 if (m_d->basename_2_pluginfile.find(bn)!=m_d->basename_2_pluginfile.end())
330 return "Channels navp1 '"+bn+"' are already provided by plugin file "
331 +m_d->basename_2_pluginfile[bn]+" (ignoring other plugins in file '"+filename+"')";
332 }
333
334
335 for (const QString& bn : providedbasenames) {
336 m_d->basename_2_pluginfile[bn] = filename;
337 m_d->basename_2_channels[bn] = std::set<IVP1ChannelWidget*>();
338 }
339
340
341 m_d->emit_basename_availableChannelListChanged();
342 m_d->emit_basename_availableUnusedChannelListChanged();
343
344
345 //Fixme: check 20 chars.
346 }
347
348
349 m_d->mainwindow->addToMessageBox( "Successfully loaded "+bn, "color:#008b00" );
350 QString out = "providing channels: "+channelsInPluginFile(filename).join(", ");
351 m_d->mainwindow->addToMessageBox( out, "color:#008b00" );
352
353
354 return "";
355}
356
357//___________________________________________________________________________________
358QStringList VP1ChannelManager::channelsInPluginFile(const QString & filename) const {
359 if (m_d->pluginfile_2_basenamesAndFactory.find(filename)==m_d->pluginfile_2_basenamesAndFactory.end())
360 return QStringList();
361 return m_d->pluginfile_2_basenamesAndFactory[filename].first;
362}
363
364//___________________________________________________________________________________
365IVP1ChannelWidget * VP1ChannelManager::Imp::constructChannel( const QString & channelbasename, QString& err, bool init ) {
366 if (basename_2_pluginfile.find(channelbasename)==basename_2_pluginfile.end()) {
367 err = "Did not find plugin providing channel named '"+channelbasename+"'";
368 return 0;
369 }
370 QString plf = basename_2_pluginfile[channelbasename];
371 //sanity:
372 assert(pluginfile_2_basenamesAndFactory.find(plf)!=pluginfile_2_basenamesAndFactory.end()&&"This should never happen!");
373 assert(pluginfile_2_basenamesAndFactory[plf].first.contains(channelbasename)&&"This should never happen!");
374 IVP1ChannelWidget * cw = pluginfile_2_basenamesAndFactory[plf].second->getChannelWidget(channelbasename);
375 if (!cw) {
376 err = "Plugin file '"+plf+"' did not provide channel navp1 '"+channelbasename+"' despite advertising this capability!";
377 return 0;
378 } else {
379 err="";
380 }
381
382 if (channelbasename!=cw->name()) {
383 err = "Actual basename of channel widget constructed by factory is not the one requested: '"+cw->name()
384 +"' vs. '"+channelbasename+"'. This is most likely due to a mistake in the plugin!!";
385 delete cw;
386 return 0;
387 }
388
389 //Cache the icon associated with this channel for future use (and override if there is already a cache):
390 QString icontext = channelTypeToIconLocation(cw->type());
391 basename2iconlocation[cw->name()]=std::move(icontext);
392
393 if (init)
394 cw->init();
395
396 //Sanity: should not have controller registered:
397 assert(channel_2_controller.find(cw)==channel_2_controller.end());
398
399 return cw;
400}
401
402//___________________________________________________________________________________
403IVP1ChannelWidget * VP1ChannelManager::getChannel( const QString& channelbasename, QString& err ) {
404 IVP1ChannelWidget * cw = m_d->constructChannel( channelbasename, err );
405 if (!cw)
406 return 0;
407 cw->setUpdatesEnabled(false);
408 cw->setCloneID(nActive(channelbasename));
409 assert(m_d->uniquename_2_channel.find(cw->unique_name())==m_d->uniquename_2_channel.end());
410 m_d->uniquename_2_channel[cw->unique_name()]=cw;
411 m_d->basename_2_channels[channelbasename].insert(cw);
412
414 m_d->scheduler->bringFromConstructedToReady(cw);//Fixme: should return bool
415 assert(cw->state()==IVP1ChannelWidget::READY);
416
417 assert(m_d->channel_2_controller.find(cw)==m_d->channel_2_controller.end());
418 QWidget * controller = cw->controllerWidget();
419 QScrollArea * scrollarea = new QScrollArea;
420 // controller->setParent(scrollarea);
421 scrollarea->setObjectName("VP1ControllerScrollArea");
422 scrollarea->setWidgetResizable(true);
423 scrollarea->setFrameShape(QFrame::NoFrame);
424 scrollarea->setFrameShadow(QFrame::Plain);
425
426
427 //scrollArea->setBackgroundRole(QPalette::Dark);
428 scrollarea->setWidget(controller);
429 m_d->channel_2_controller[cw] = scrollarea;
430
432 m_d->emit_basename_availableUnusedChannelListChanged();
434 cw->setUpdatesEnabled(true);
435
436 return cw;
437}
438
439//___________________________________________________________________________________
441 assert(m_d->channel_2_controller.find(cw)!=m_d->channel_2_controller.end());
442 return m_d->channel_2_controller[cw];
443}
444
445//___________________________________________________________________________________
446unsigned VP1ChannelManager::nActive( const QString & channelbasename ) const {
447 if (m_d->basename_2_channels.find(channelbasename)==m_d->basename_2_channels.end())
448 return 0;
449 return m_d->basename_2_channels[channelbasename].size();
450}
451
452//fixme: Always check uniqueness (and <20chars) of basenames!
453
454//___________________________________________________________________________________
456 if (m_d->uniquename_2_channel.find(uniquename)==m_d->uniquename_2_channel.end())
457 return 0;
458 return m_d->uniquename_2_channel[uniquename];
459}
460
461//___________________________________________________________________________________
462bool VP1ChannelManager::uniqueNameExists(const QString & uniquename) const {
463 return (m_d->uniquename_2_channel.find(uniquename)!=m_d->uniquename_2_channel.end());
464}
465
466//___________________________________________________________________________________
467bool VP1ChannelManager::baseNameExists(const QString & basename) const {
468 return (m_d->basename_2_pluginfile.find(basename)!=m_d->basename_2_pluginfile.end());
469}
470
471//___________________________________________________________________________________
473 QStringList l;
474 std::map<QString,IVP1ChannelWidget*>::iterator it = m_d->uniquename_2_channel.begin();
475 std::map<QString,IVP1ChannelWidget*>::iterator itE = m_d->uniquename_2_channel.end();
476
477 for (;it!=itE;++it)
478 l << it->first;
479
480 return l;
481}
482
483
484//___________________________________________________________________________________
486 QStringList l;
487
488 std::map<QString,QString>::const_iterator it = basename_2_pluginfile.begin();
489 std::map<QString,QString>::const_iterator itE = basename_2_pluginfile.end();
490 for (;it!=itE;++it) {
491 l << it->first;
492 }
493 channelmanager->availableChannelListChanged(l);
494
495}
496
497//___________________________________________________________________________________
499 QStringList l;
500 std::map<QString,QString>::const_iterator it = m_d->basename_2_pluginfile.begin();
501 std::map<QString,QString>::const_iterator itE = m_d->basename_2_pluginfile.end();
502 for (;it!=itE;++it) {
503 l << it->first;
504 }
505 return l;
506}
507
508//___________________________________________________________________________________
510 QStringList l;
511
512 std::map<QString,QString>::const_iterator it = basename_2_pluginfile.begin();
513 std::map<QString,QString>::const_iterator itE = basename_2_pluginfile.end();
514 for (;it!=itE;++it) {
515 if (channelmanager->nActive(it->first)==0)
516 l << it->first;
517 }
518
519 channelmanager->availableUnusedChannelListChanged(l);
520}
521
522//___________________________________________________________________________________
524 std::map<QString,std::pair<QStringList,IVP1ChannelWidgetFactory *> >::const_iterator
525 it, itE = m_d->pluginfile_2_basenamesAndFactory.end();
526
527 QStringList l;
528 for( it = m_d->pluginfile_2_basenamesAndFactory.begin(); it!=itE; ++it ) {
529 l<<QFileInfo(it->first).fileName();
530 }
531 return l;
532}
533
534//___________________________________________________________________________________
536 std::map<QString,QPluginLoader*>::const_iterator it = m_d->pluginfile_2_pluginloader.begin();
537 std::map<QString,QPluginLoader*>::const_iterator itE = m_d->pluginfile_2_pluginloader.end();
538 QStringList l;
539 for(;it!=itE;++it) {
540 l<<it->first;
541 }
542 return l;
543}
544
545//___________________________________________________________________________________
546QStringList VP1ChannelManager::basename2UniqueNames(const QString & basename) const {
547
548 if (m_d->basename_2_channels.find(basename)==m_d->basename_2_channels.end())
549 return QStringList();
550
551 std::set<IVP1ChannelWidget*>::const_iterator it = m_d->basename_2_channels[basename].begin();
552 std::set<IVP1ChannelWidget*>::const_iterator itE = m_d->basename_2_channels[basename].end();
553
554 QStringList l;
555 for (;it!=itE;++it) {
556 l << (*it)->unique_name();
557 }
558 return l;
559}
560
561//___________________________________________________________________________________
563 if (m_d->basename_2_channels.find(basename)==m_d->basename_2_channels.end())
564 return false;
565 return !m_d->basename_2_channels[basename].empty();
566}
567
568
569//___________________________________________________________________________________
571{
572 if (type==IVP1ChannelWidget::THREEDIMENSIONAL) return ":/vp1/icons/icons/3d_32x32.png";
573 if (type==IVP1ChannelWidget::TWODIMENSIONAL) return ":/vp1/icons/icons/kivio_32x32.png";//Fixme: Better icon.
574 if (type==IVP1ChannelWidget::NUMBERS) return ":/vp1/icons/icons/kcalc_32x32.png";
575 if (type==IVP1ChannelWidget::HISTOGRAM) return ":/vp1/icons/icons/kchart_32x32.png";
576 if (type==IVP1ChannelWidget::UNKNOWN) return ":/vp1/icons/icons/help_32x32.png";
577 return "";
578}
579
580//___________________________________________________________________________________
581bool VP1ChannelManager::hasRefreshingSystem(const QString& uniquename) const
582{
583 IVP1ChannelWidget*cw = uniqueName2Channel(uniquename);
584 return cw ? cw->hasRefreshingSystem() : false;
585}
586
587//___________________________________________________________________________________
588QString VP1ChannelManager::getIconLocation(const QString& channelname, const bool& isbasename)
589{
590 if (!isbasename) {
591 IVP1ChannelWidget* cw = uniqueName2Channel(channelname);
592 if (!cw)
593 return "";
594 return m_d->channelTypeToIconLocation(cw->type());
595 }
596
597 if (m_d->basename2iconlocation.contains(channelname))
598 return m_d->basename2iconlocation[channelname];
599
600 //We have to briefly construct a channel in order to get its type.
601 //The following create and destruct maneouver is to get a proper
602 //cache of the icontext associated with the channel:
603 QString err;
604 IVP1ChannelWidget * cw = m_d->constructChannel( channelname, err, false /*don't init()*/ );
605 if (!cw)
606 return "";
607 cw->deleteControllers();
608 delete cw;
609 // cppcheck-suppress deallocuse
610 assert(m_d->channel_2_controller.find(cw)==m_d->channel_2_controller.end());
611
612 //Try again;
613 if (m_d->basename2iconlocation.contains(channelname))
614 return m_d->basename2iconlocation[channelname];
615 return "";
616}
virtual QStringList channelWidgetsProvided() const =0
virtual Type type() const =0
virtual void init()=0
void setCloneID(unsigned id)
const QString unique_name() const
const QString & name() const
std::map< QString, std::set< IVP1ChannelWidget * > > basename_2_channels
std::map< QString, std::pair< QStringList, IVP1ChannelWidgetFactory * > > pluginfile_2_basenamesAndFactory
void emit_basename_availableUnusedChannelListChanged()
QString channelTypeToIconLocation(const IVP1ChannelWidget::Type &type) const
std::map< IVP1ChannelWidget *, QWidget * > channel_2_controller
QList< QObject * > additionalOwnedObjects
std::map< QString, QPluginLoader * > pluginfile_2_pluginloader
QMap< QString, QString > basename2iconlocation
VP1ExecutionScheduler * scheduler
std::map< QString, QString > basename_2_pluginfile
std::map< QString, IVP1ChannelWidget * > uniquename_2_channel
IVP1ChannelWidget * constructChannel(const QString &channelbasename, QString &err, bool init=true)
VP1ChannelManager * channelmanager
QStringList basename2UniqueNames(const QString &basename) const
bool hasRefreshingSystem(const QString &uniquename) const
bool baseNameExists(const QString &) const
bool uniqueNameExists(const QString &) const
QStringList serializePluginInfo() const
bool channelWithBasenameIsLoaded(const QString &basename) const
QStringList channelsInPluginFile(const QString &filename) const
bool deleteChannel(const QString &channeluniquename)
void channelUncreated(IVP1ChannelWidget *)
IVP1ChannelWidget * getChannel(const QString &channelbasename, QString &err)
QString loadPluginFile(const QString &filename)
QStringList currentPluginFiles() const
QString getIconLocation(const QString &channelname, const bool &isbasename=true)
bool unloadPluginFile(const QString &filename)
unsigned nActive(const QString &channelbasename) const
QWidget * getController(IVP1ChannelWidget *)
VP1ChannelManager(VP1ExecutionScheduler *, VP1MainWindow *)
QStringList uniquenames() const
void uniquename_channelListChanged(const QStringList &)
QStringList availableChannelList()
IVP1ChannelWidget * uniqueName2Channel(const QString &uniquename) const
void newChannelCreated(IVP1ChannelWidget *)
static void messageVerbose(const QString &)
Definition VP1Msg.cxx:84
static void message(const QString &, IVP1System *sys=0)
Definition VP1Msg.cxx:30
std::string basename(std::string name)
Definition utils.cxx:207