41#include <QApplication>
42#include <QInputDialog>
68 QMainWindow *
name2tab(
const QString& tabname);
81 bool checkChannelNameExists(
const QString& channelbasename,
const bool& isuniquename,
const bool& checkfornonexistance =
false)
const;
99 QMap<QString,QByteArray>&tab2arrangements)
const;
113 : QObject(parent),
m_d(new
Imp(this,tw,
cm)) {
115 m_d->dontEmitVisibilityChanges=
false;
117 connect(tw->
getVP1TabBar(),SIGNAL(contextMenu(
int,
const QPoint& )),
127 while (
m_d->tabwidget->count()>0) {
139 channel->launchStereoEditor();
162 QMessageBox::critical(0,
"Error - Tab "+tabname+
" does not exists",
163 "Tab <i>"+tabname+
"</i> does not exists.",QMessageBox::Ok,QMessageBox::Ok);
174 QMessageBox::critical(0,
"Error - Tab "+tabname+
" already exists",
175 "Tab <i>"+tabname+
"</i> already exists.",QMessageBox::Ok,QMessageBox::Ok);
183 if (tabname.isEmpty()) {
184 QMessageBox::critical(0,
"Error - Empty tab name provided",
185 "Empty tab name provided.",QMessageBox::Ok,QMessageBox::Ok);
193 if (channelname.isEmpty()) {
194 QMessageBox::critical(0,
"Error - Empty channel name provided",
195 "Empty channel name provided.",QMessageBox::Ok,QMessageBox::Ok);
198 if ( checkfornonexistance == ( isuniquename ?
channelmanager->uniqueNameExists(channelname)
200 QString tmp = ( checkfornonexistance ?
"already":
"does not" );
201 QMessageBox::critical(0,
"Error - Channel "+channelname+
" "+tmp+
" exists",
202 "Channel <i>"+channelname+
"</i> "+tmp+
" exists.",QMessageBox::Ok,QMessageBox::Ok);
213 return QStringList();
218 l << (*it)->unique_name();
230 return QStringList();
238 if (!
m_d->checkTabnameNotExists(tabname))
return;
239 bool save =
m_d->dontEmitVisibilityChanges;
240 m_d->dontEmitVisibilityChanges=
true;
242 QMainWindow * t =
new QMainWindow();
243 t->setDockNestingEnabled(
true);
245 m_d->tabwidget->addTab(t,tabname);
247 m_d->tabwidget->insertTab(
index,t,tabname);
249 m_d->name_2_tab[tabname]=t;
250 m_d->tab_2_channelwidgets[t] = std::set<IVP1ChannelWidget*>();
252 m_d->dontEmitVisibilityChanges=save;
259 if (!(
m_d->fullscreen_dockwidget||
m_d->fullscreen_tab))
262 bool save =
m_d->dontEmitVisibilityChanges;
263 m_d->dontEmitVisibilityChanges=
true;
264 qApp->removeEventFilter(
this);
265 QWidget * focuswidget = qApp->focusWidget();
267 if (
m_d->fullscreen_dockwidget) {
268 assert(
m_d->fullscreen_dockwidget&&
m_d->fullscreen_channelwidget);
269 m_d->fullscreen_dockwidget->ensureCWHasParent();
270 m_d->fullscreen_channelwidget->showNormal();
271 m_d->fullscreen_dockwidget=0;
272 m_d->fullscreen_channelwidget=0;
274 assert(
m_d->fullscreen_tab);
275 QWidget * dummywidget=
m_d->tabwidget->widget(
m_d->fullscreen_tabindex);
276 m_d->tabwidget->removeTab(
m_d->fullscreen_tabindex);
277 m_d->tabwidget->insertTab(
m_d->fullscreen_tabindex,
m_d->fullscreen_tab,
m_d->fullscreen_tabname );
279 m_d->tabwidget->setCurrentIndex(
m_d->fullscreen_tabindex);
281 assert(
m_d->tab_2_channelwidgets.find(
m_d->fullscreen_tab)!=
m_d->tab_2_channelwidgets.end());
282 std::set<IVP1ChannelWidget*>::const_iterator it =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].begin();
283 std::set<IVP1ChannelWidget*>::const_iterator itE =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].end();
284 for (;it!=itE;++it) {
285 assert(
m_d->channelwidget_2_dockwidget.find(*it)!=
m_d->channelwidget_2_dockwidget.end());
287 dock->setFeatures(VP1DockWidget::DockWidgetMovable|VP1DockWidget::DockWidgetFloatable);
288 if (
m_d->fullscreen_floatingdocks.find(dock)!=
m_d->fullscreen_floatingdocks.end())
289 dock->setFloating(
true);
291 m_d->fullscreen_tabname =
"";
292 m_d->fullscreen_tabindex = -1;
293 m_d->fullscreen_tab = 0;
294 m_d->fullscreen_floatingdocks.clear();
296 if (focuswidget&&!focuswidget->hasFocus())
297 focuswidget->setFocus(Qt::OtherFocusReason);
298 m_d->dontEmitVisibilityChanges=save;
309 if (event->type()==QEvent::Close) {
314 if (event->type()!=QEvent::KeyPress)
317 QKeyEvent *keyEvent =
static_cast<QKeyEvent*
>(event);
319 if (keyEvent->key()!=Qt::Key_Escape)
333 if (
m_d->selecteddockwidget == dw )
336 if (
m_d->selecteddockwidget)
337 m_d->selecteddockwidget->setUnselected();
339 m_d->selecteddockwidget=dw;
353 assert(
m_d->channelwidget_2_dockwidget.find(cw)!=
m_d->channelwidget_2_dockwidget.end());
361 assert(
m_d->channelwidget_2_dockwidget.find(cw)!=
m_d->channelwidget_2_dockwidget.end());
363 bool save =
m_d->dontEmitVisibilityChanges;
364 m_d->dontEmitVisibilityChanges=
true;
365 m_d->fullscreen_dockwidget=dock;
366 m_d->fullscreen_channelwidget=cw;
369 cw->showFullScreen();
370 qApp->installEventFilter(
this);
371 m_d->dontEmitVisibilityChanges=save;
380 if(!
m_d->selecteddockwidget)
388 if(!
m_d->selecteddockwidget)
391 return m_d->selecteddockwidget->channelWidget()->unique_name();
399 if (
m_d->tabwidget->tabText(
index)==tabname)
402 if (
index >=
m_d->tabwidget->count())
406 assert(
m_d->fullscreen_tabname.isEmpty());
407 assert(
m_d->fullscreen_tabindex==-1);
408 assert(!
m_d->fullscreen_tab);
409 assert(
m_d->fullscreen_floatingdocks.empty());
411 bool save =
m_d->dontEmitVisibilityChanges;
412 m_d->dontEmitVisibilityChanges=
true;
416 m_d->fullscreen_tabname =
m_d->tabwidget->tabText(
m_d->fullscreen_tabindex);
417 assert(
m_d->name_2_tab.find(
m_d->fullscreen_tabname)!=
m_d->name_2_tab.end());
418 m_d->fullscreen_tab =
m_d->name_2_tab[
m_d->fullscreen_tabname];
420 assert(
m_d->tab_2_channelwidgets.find(
m_d->fullscreen_tab)!=
m_d->tab_2_channelwidgets.end());
421 std::set<IVP1ChannelWidget*>::const_iterator it =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].begin();
422 std::set<IVP1ChannelWidget*>::const_iterator itE =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].end();
423 for (;it!=itE;++it) {
424 assert(
m_d->channelwidget_2_dockwidget.find(*it)!=
m_d->channelwidget_2_dockwidget.end());
426 if (dock->isFloating()) {
427 m_d->fullscreen_floatingdocks.insert(dock);
428 dock->setFloating(
false);
430 dock->setFeatures(VP1DockWidget::DockWidgetMovable);
434 m_d->tabwidget->removeTab(
m_d->fullscreen_tabindex);
435 m_d->fullscreen_tab->hide();
436 m_d->fullscreen_tab->setParent(0);
437 m_d->tabwidget->insertTab (
m_d->fullscreen_tabindex,
new QWidget(),
m_d->fullscreen_tabname );
438 m_d->fullscreen_tab->showFullScreen();
440 it =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].begin();
441 itE =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].end();
442 for (;it!=itE;++it) {
443 assert(
m_d->channelwidget_2_dockwidget.find(*it)!=
m_d->channelwidget_2_dockwidget.end());
448 qApp->installEventFilter(
this);
449 m_d->dontEmitVisibilityChanges=save;
457 if (
m_d->tabwidget->count()==0)
466 return m_d->selecteddockwidget ?
m_d->selecteddockwidget->channelWidget() : 0;
472 #if defined BUILDVP1LIGHT
478 if (
m_d->channelwidget_2_dockwidget.size()&&checkDisallowMultipleChannels) {
479 QMessageBox::critical(0,
"Error - Not allowed to open channel",
480 "The possibility to launch multiple channels has been disabled by the environment variable VP1_DISALLOW_MULTIPLE_CHANNELS."
481 " This was likely set since some badly written 3D drivers have been known to cause crashes when showing multiple 3D views."
482 "\n In order to launch a new channel you must thus first remove the already active channel."
483 "\n To disable this behaviour don't set VP1_DISALLOW_MULTIPLE_CHANNELS, or set it to \"0'.",QMessageBox::Ok,QMessageBox::Ok);
487 if (!
m_d->checkTabnameExists(tabname))
return 0;
488 if (!
m_d->checkChannelNameExists(channelbasename,
false))
return 0;
493 if (!err.isEmpty()) {
494 QMessageBox::critical(0,
"Error - could not get channel: "+channelbasename,
495 "Could not get channel: "+channelbasename
496 +
"\n\nReason: "+err,QMessageBox::Ok,QMessageBox::Ok);
501 bool save =
m_d->dontEmitVisibilityChanges;
502 m_d->dontEmitVisibilityChanges=
true;
503 cw->setUpdatesEnabled(
false);
510 QMainWindow * tab =
m_d->name_2_tab[tabname];
511 tab->addDockWidget(Qt::TopDockWidgetArea, dock);
513 assert(
m_d->channelwidget_2_dockwidget.find(cw)==
m_d->channelwidget_2_dockwidget.end());
514 m_d->channelwidget_2_dockwidget[cw]=dock;
515 assert(
m_d->tab_2_channelwidgets.find(tab)!=
m_d->tab_2_channelwidgets.end());
516 m_d->tab_2_channelwidgets[tab].insert(cw);
517 cw->setUpdatesEnabled(
true);
518 m_d->dontEmitVisibilityChanges=save;
525 if (!
m_d->checkTabnameExists(tabname))
return;
526 if (!
m_d->checkTabnameNotExists(newtabname))
return;
528 QMainWindow * tab =
m_d->name_2_tab[tabname];
530 m_d->name_2_tab.erase(
m_d->name_2_tab.find(tabname));
531 m_d->name_2_tab[newtabname]=tab;
532 int tabindex =
m_d->tabwidget->indexOf(tab);
533 assert(tabindex!=-1);
534 m_d->tabwidget->setTabText ( tabindex, newtabname );
541 for (
int i = 0; i <
m_d->tabwidget->count(); ++i) {
542 l<<
m_d->tabwidget->tabText(i);
551 if (!
m_d->checkTabnameExists(tabname))
return;
553 bool save =
m_d->dontEmitVisibilityChanges;
554 m_d->dontEmitVisibilityChanges=
true;
556 assert(
m_d->name_2_tab.find(tabname)!=
m_d->name_2_tab.end());
557 QMainWindow * tab =
m_d->name_2_tab[tabname];
559 assert(
m_d->tab_2_channelwidgets.find(tab)!=
m_d->tab_2_channelwidgets.end());
563 std::set<IVP1ChannelWidget*>::const_iterator it =
m_d->tab_2_channelwidgets[tab].begin();
564 std::set<IVP1ChannelWidget*>::const_iterator itE =
m_d->tab_2_channelwidgets[tab].end();
565 for (;it!=itE;++it) {
566 (*it)->setUpdatesEnabled(
false);
570 while(
m_d->tab_2_channelwidgets[tab].size()>0) {
576 m_d->name_2_tab.erase(
m_d->name_2_tab.find(tabname));
577 int i =
m_d->tabwidget->indexOf(tab);
579 m_d->tabwidget->removeTab(i);
584 m_d->dontEmitVisibilityChanges=save;
593 for(
const QString& tab :
tabList() ) {
604 if (!
m_d->checkChannelNameExists(channeluniquename,
true))
return;
610 if (
m_d->selecteddockwidget&&cw==
m_d->selecteddockwidget->channelWidget())
613 QString bn = cw->
name();
614 cw->setUpdatesEnabled(
false);
616 assert(
m_d->channelwidget_2_dockwidget.find(cw)!=
m_d->channelwidget_2_dockwidget.end());
620 assert(
m_d->channelwidget_2_dockwidget.find(cw)!=
m_d->channelwidget_2_dockwidget.end());
621 m_d->channelwidget_2_dockwidget.erase(
m_d->channelwidget_2_dockwidget.find(cw));
624 QMainWindow * tab =
m_d->channel2tab(cw);
631 tab->setUpdatesEnabled(
false);
632 tab->removeDockWidget(dw);
636 assert(
m_d->tab_2_channelwidgets[tab].find(cw)!=
m_d->tab_2_channelwidgets[tab].end());
637 m_d->tab_2_channelwidgets[tab].erase(
m_d->tab_2_channelwidgets[tab].find(cw));
649 tab->setUpdatesEnabled(
true);
652 if (
m_d->selecteddockwidget==dw) {
653 m_d->selecteddockwidget=0;
664 for (;it!=itE;++it) {
665 if (it->second.find(cw)!=it->second.end())
685 if (!
m_d->checkTabnameExists(tabname))
return;
686 if (!
m_d->checkChannelNameExists(channeluniquename,
true))
return;
688 QMainWindow * tab_new =
m_d->name_2_tab[tabname];
693 assert(
m_d->channelwidget_2_dockwidget.find(cw)!=
m_d->channelwidget_2_dockwidget.end());
697 QMainWindow * tab_old =
m_d->channel2tab(cw);
700 if (tab_old==tab_new)
703 tab_old->removeDockWidget(dw);
704 dw->setParent(tab_new);
705 tab_new->addDockWidget(Qt::TopDockWidgetArea, dw);
709 assert(
m_d->tab_2_channelwidgets.find(tab_old)!=
m_d->tab_2_channelwidgets.end());
710 assert(
m_d->tab_2_channelwidgets.find(tab_new)!=
m_d->tab_2_channelwidgets.end());
711 assert(
m_d->tab_2_channelwidgets[tab_old].find(cw)!=
m_d->tab_2_channelwidgets[tab_old].end());
712 assert(
m_d->tab_2_channelwidgets[tab_new].find(cw)==
m_d->tab_2_channelwidgets[tab_new].end());
713 m_d->tab_2_channelwidgets[tab_old].erase(
m_d->tab_2_channelwidgets[tab_old].find(cw));
714 m_d->tab_2_channelwidgets[tab_new].insert(cw);
720 if (!
m_d->checkTabnameExists(tabname))
return;
721 if (!
m_d->checkChannelNameExists(channeluniquename,
true))
return;
735 if (!
m_d->checkTabnameExists(oldtabname))
return;
736 if (!
m_d->checkTabnameNotExists(newtabname))
return;
740 assert(
m_d->name_2_tab.find(newtabname)!=
m_d->name_2_tab.end());
742 QMainWindow * oldtab =
m_d->name_2_tab[oldtabname];
744 assert(
m_d->tab_2_channelwidgets.find(oldtab)!=
m_d->tab_2_channelwidgets.end());
745 std::set<IVP1ChannelWidget*>::const_iterator it =
m_d->tab_2_channelwidgets[oldtab].begin();
746 std::set<IVP1ChannelWidget*>::const_iterator itE =
m_d->tab_2_channelwidgets[oldtab].end();
748 for (;it!=itE;++it) {
757 QMainWindow * newtab =
m_d->name_2_tab[newtabname];
758 QByteArray state = oldtab->saveState();
759 if (!newtab->restoreState(state))
760 QMessageBox::warning(0,
"Warning - Problems cloning channel arrangement",
761 "Problems cloning channel arrangement.",QMessageBox::Ok,QMessageBox::Ok);
768 if (filename.isEmpty()) {
769 QMessageBox::critical(0,
"Error - Empty file name provided",
770 "Empty file name provided.",QMessageBox::Ok,QMessageBox::Ok);
774 QFileInfo fi(filename);
776 if (!fi.isWritable()) {
777 QMessageBox::critical(0,
"Error - could not save to file "+filename,
778 "Could not save to file: <i>"+filename+
"</i>"
779 +
"<br/><br/>Reason: File exists already and is write protected",QMessageBox::Ok,QMessageBox::Ok);
783 int ret = QMessageBox::question(0,
"File already exists: "+filename,
784 "The file <i>"+filename+
"</i> already exists.\n"
785 "Override this file?",
786 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
787 if (ret==QMessageBox::Cancel)
792 QFile
file(filename);
793 if (!
file.open(QIODevice::WriteOnly)) {
794 QMessageBox::critical(0,
"Error - problems writing to file "+filename,
795 "Problems writing to file: <i>"+filename+
"</i>",QMessageBox::Ok,QMessageBox::Ok);
800 QMap<QString,QMultiMap<QString,ChanState> > tab2channels;
801 QMap<QString,QByteArray> tab2arrangements;
802 m_d->serializeTabAndChannelConfigInfo(tab2channels, tab2arrangements);
805 QByteArray byteArray;
806 QBuffer buffer(&byteArray);
807 buffer.open(QIODevice::WriteOnly);
808 QDataStream out(&buffer);
809 out<<QString(
"This is an automatically generated config file for VP1. [cfg version 003]" );
810 out<<
m_d->channelmanager->serializePluginInfo();
812 out<<tab2arrangements;
814 out<<QString(
"This is the end of the automatically generated config file for VP1." );
817 QDataStream outfile(&
file);
818 outfile<<qCompress(byteArray).toBase64();
825 if (filename.isEmpty()) {
826 QMessageBox::critical(0,
"Error - Empty file name provided",
827 "Empty file name provided.",QMessageBox::Ok,QMessageBox::Ok);
830 QFileInfo fi(filename);
832 QMessageBox::critical(0,
"Error - file does not exists: "+filename,
833 "File does not exists: <i>"+filename+
"</i>",QMessageBox::Ok,QMessageBox::Ok);
836 if (!fi.isReadable()) {
837 QMessageBox::critical(0,
"Error - file is not readable: "+filename,
838 "File is not readable: <i>"+filename+
"</i>",QMessageBox::Ok,QMessageBox::Ok);
842 QFile
file(filename);
843 if (!
file.open(QIODevice::ReadOnly)) {
844 QMessageBox::critical(0,
"Error - problems opening file "+filename,
845 "Problems opening file: <i>"+filename+
"</i>",QMessageBox::Ok,QMessageBox::Ok);
851 QStringList pluginfiles;
852 QMap<QString,QMultiMap<QString,ChanState> > tab2channels;
853 QMap<QString,QByteArray> tab2arrangements;
854 QStringList tabs_orded;
856 QByteArray byteArray64;
857 QDataStream infile(&
file);
858 infile >> byteArray64;
860 QByteArray byteArray = qUncompress(QByteArray::fromBase64(byteArray64));
862 QBuffer buffer(&byteArray);
863 buffer.open(QIODevice::ReadOnly);
864 QDataStream in(&buffer);
868 in >> tab2arrangements;
873 if (
head!=
"This is an automatically generated config file for VP1. [cfg version 003]"
874 ||foot!=
"This is the end of the automatically generated config file for VP1."
875 ||tab2channels.count()!=tab2arrangements.count()) {
876 QMessageBox::critical(0,
"Error - file not in correct format: "+filename,
877 "File not in correct format: <i>"+filename+
"</i>",QMessageBox::Ok,QMessageBox::Ok);
881 QStringList pf_withproblem;
882 QStringList errormessage;
885 QString sharedlibsuffix_correct =
".dylib";
886 QString sharedlibsuffix_wrong =
".so";
888 QString sharedlibsuffix_correct =
".so";
889 QString sharedlibsuffix_wrong =
".dylib";
892 for(QString pf : pluginfiles) {
893 if (pf.endsWith(sharedlibsuffix_wrong)) {
894 pf.replace(sharedlibsuffix_wrong, sharedlibsuffix_correct);
897 if (!availableplugins.contains(pf)) {
899 errormessage<<
"Could not locate " + pf;
902 QString pfabsolute = availableplugins[pf];
904 if (
m_d->channelmanager->channelsInPluginFile(pfabsolute).empty())
905 err =
m_d->channelmanager->loadPluginFile(pfabsolute);
906 if (!err.isEmpty()) {
907 pf_withproblem<<pfabsolute;
912 if (!pf_withproblem.empty()) {
913 assert(pf_withproblem.count()==errormessage.count());
915 for (
int i = 0; i<pf_withproblem.count();++i) {
916 tmp += pf_withproblem.value(i)+
": "+errormessage.value(i)+
"\n";
918 QMessageBox::warning(0,
"Warning - could not load all plugins",
919 "Some or more plugins did not load properly:\n\n"+tmp,QMessageBox::Ok,QMessageBox::Ok);
922 QString channelsFailureMsg;
923 QString tabArrangementFailureMsg;
925 QString lastaddedtab;
927 for (
const QString& newtabname_infile : tabs_orded) {
929 if (!tab2channels.contains(newtabname_infile)||!tab2arrangements.contains(newtabname_infile)) {
930 QMessageBox::critical(0,
"Error - file not in correct format: "+filename,
931 "File not in correct format: <i>"+filename+
"</i>",QMessageBox::Ok,QMessageBox::Ok);
937 QMainWindow * existingtab =
m_d->name2tab(newtabname_infile);
939 if (
m_d->tab_2_channelwidgets.find(existingtab)==
m_d->tab_2_channelwidgets.end()
940 ||
m_d->tab_2_channelwidgets[existingtab].empty())
946 if (
m_d->channelwidget_2_dockwidget.empty()
947 &&
m_d->name_2_tab.size()==1
948 &&
m_d->name_2_tab.begin()->first==
"My Tab")
953 if (!
m_d->checkTabnameExists(newtabname))
955 lastaddedtab=newtabname;
957 QMapIterator<QString,ChanState> it( tab2channels.value(newtabname_infile) );
959 while (it.hasNext()) {
963 if (!
m_d->channelmanager->baseNameExists(it.key())) {
964 channelsFailureMsg += it.key()+
" (tab "+newtabname+
")"+
"\n";
970 channelsFailureMsg += it.key()+
" (tab "+newtabname+
")"+
"\n";
975 assert(
m_d->name_2_tab.find(newtabname)!=
m_d->name_2_tab.end());
976 QMainWindow * tab =
m_d->name_2_tab.find(newtabname)->second;
977 QByteArray state = tab2arrangements.value(newtabname_infile);
979 if (!state.isEmpty()) {
980 if (!tab->restoreState(state,0)) {
981 tabArrangementFailureMsg += newtabname+
"\n";
985 if (!channelsFailureMsg.isEmpty()) {
986 QMessageBox::warning(0,
"Warning - could not start all channels",
987 "Some or more channels were not available to start:\n\n"
988 +channelsFailureMsg,QMessageBox::Ok,QMessageBox::Ok);
990 if (!tabArrangementFailureMsg.isEmpty()) {
991 QMessageBox::warning(0,
"Warning - could not arrange channels in all tabs",
992 "The arrangement of channels could not be properly determined withing the following tabs:\n\n"
993 +tabArrangementFailureMsg,QMessageBox::Ok,QMessageBox::Ok);
995 if (!lastaddedtab.isEmpty())
1001 QMap<QString,QByteArray>& tab2arrangements)
const {
1003 tab2channels.clear();
1004 tab2arrangements.clear();
1005 for (
int i = 0; i<
tabwidget->count();++i) {
1006 QString tabname =
tabwidget->tabText(i);
1008 QMainWindow * tab =
name_2_tab.find(tabname)->second;
1009 QMultiMap<QString,ChanState> channelsinfo;
1012 std::set<IVP1ChannelWidget*>::const_iterator it = itcws->second.begin();
1013 std::set<IVP1ChannelWidget*>::const_iterator itE = itcws->second.end();
1014 for (;it!=itE;++it) {
1016 tabmanager->serializeChannelState(*it,chanstate);
1017 channelsinfo.insert((*it)->name(),chanstate);
1019 tab2channels.insert(tabname,channelsinfo);
1022 tab2arrangements.insert(tabname,tab->saveState(0));
1028 QString newtabname=oldtabname;
1030 while (
m_d->name_2_tab.find(newtabname)!=
m_d->name_2_tab.end())
1031 newtabname=oldtabname+
" "+QString::number(++i);
1037 if (
m_d->tabwidget->count()==0)
1039 return m_d->tabwidget->tabText(
m_d->tabwidget->currentIndex());
1044 return m_d->tabwidget->count();
1051 std::cout<<
"currentindex:"<<
tabwidget->currentIndex()<<std::endl;
1052 std::cout<<
"nextindex:"<<(
tabwidget->currentIndex() + 1) %
tabwidget->count()<<std::endl;
1067 int newindex =
tabwidget->currentIndex() - 1;
1070 QMainWindow*prevtab =
static_cast<QMainWindow*
>(
tabwidget->widget(newindex %
tabwidget->count()));
1080 for (
int i = 0; i <
m_d->tabwidget->count(); ++i) {
1081 if (
m_d->tabwidget->tabText(i)==tabname) {
1088 if (itarget==
m_d->tabwidget->currentIndex())
1091 bool save =
m_d->dontEmitVisibilityChanges;
1092 m_d->dontEmitVisibilityChanges=
true;
1094 bool fullscreentab = (
m_d->fullscreen_tab!=0);
1095 if (
m_d->fullscreen_channelwidget||
m_d->fullscreen_tab)
1098 m_d->tabwidget->setCurrentIndex(itarget);
1101 m_d->dontEmitVisibilityChanges=save;
1109 if (
m_d->tabwidget->count()<=1)
1111 assert(!
m_d->fullscreen_channelwidget);
1112 if (
m_d->fullscreen_tab) {
1113 bool save =
m_d->dontEmitVisibilityChanges;
1114 m_d->dontEmitVisibilityChanges=
true;
1118 m_d->dontEmitVisibilityChanges=save;
1120 m_d->tabwidget->setCurrentIndex((
m_d->tabwidget->currentIndex() + 1) %
m_d->tabwidget->count());
1125 assert(!
m_d->fullscreen_channelwidget);
1126 assert(!
m_d->fullscreen_tab);
1127 if (
m_d->tabwidget->count()<=1)
1129 int newindex =
m_d->tabwidget->currentIndex() - 1;
1131 newindex +=
m_d->tabwidget->count();
1132 m_d->tabwidget->setCurrentIndex( newindex %
m_d->tabwidget->count());
1138 QString tabname =
m_d->tabwidget->tabText(i);
1145 QAction* pFullScreenAction =
menu.addAction(
"Show &full Screen");
1146 menu.addSeparator();
1147 QAction* pRenameAction =
menu.addAction(
"Re&name tab");
1148 QAction* pDeleteAction =
menu.addAction(
"&Remove tab");
1149 menu.addSeparator ();
1150 QAction* pInsertNewAction =
menu.addAction(
"&Insert new tab");
1151 QAction* pCloneAction =
menu.addAction(
"&Clone tab");
1152 menu.addSeparator ();
1153 QAction* pAddChannelAction =
menu.addAction(
"&Add channel");
1154 QAction* pRemoveChannelAction =
menu.addAction(
"R&emove channel");
1156 QMenu menu_addchan(
m_d->tabwidget);
1157 QStringList chnls =
m_d->channelmanager->availableChannelList();
1158 if (chnls.empty()) {
1159 menu_addchan.addAction(
"No channels available")->setEnabled(
false);
1161 for (
const QString& chnl : chnls) {
1162 QString iconloc =
m_d->channelmanager->getIconLocation(chnl,
true);
1164 if (iconloc.isEmpty())
1165 pChnlAct = menu_addchan.addAction(chnl);
1167 pChnlAct = menu_addchan.addAction(QIcon(iconloc),chnl);
1168 pChnlAct->setData(
"ADDCHAN");
1171 pAddChannelAction->setMenu(&menu_addchan);
1172 QStringList chnls_rem =
m_d->channelsInTab(tabname);
1173 if (chnls_rem.empty())
1174 pFullScreenAction->setEnabled(
false);
1175 QMenu menu_remchan(
m_d->tabwidget);
1176 if (chnls_rem.empty()) {
1177 menu_remchan.addAction(
"No channels in tab")->setEnabled(
false);
1179 for (
const QString& chnl : chnls_rem) {
1180 QString iconloc =
m_d->channelmanager->getIconLocation(chnl,
false);
1182 if (iconloc.isEmpty())
1183 pChnlAct = menu_remchan.addAction(chnl);
1185 pChnlAct = menu_remchan.addAction(QIcon(iconloc),chnl);
1186 pChnlAct->setData(
"REMCHAN");
1189 pRemoveChannelAction->setMenu(&menu_remchan);
1193 QAction * selAct =
menu.exec(p);
1197 if (selAct==pFullScreenAction) {
1201 if (selAct==pRenameAction) {
1203 QString text = QInputDialog::getText( 0,
"Rename tab '"+tabname+
"'",
"Rename tab '"+tabname+
"' to:",
1204 QLineEdit::Normal, tabname, &ok );
1205 if (!ok||text==tabname)
1210 if (selAct==pDeleteAction) {
1214 if (selAct==pInsertNewAction) {
1216 QString newtabname = QInputDialog::getText( 0,
"New Tab Name",
"New tab name:",
1218 if (!ok||newtabname.isEmpty())
1223 if (selAct==pCloneAction) {
1225 QString newtabname = QInputDialog::getText( 0,
"Cloning '"+tabname+
"'.",
"Cloning '"+tabname+
"'. Name of new tab:",
1227 if (!ok||newtabname.isEmpty())
1232 if (selAct==pAddChannelAction) {
1236 if (selAct->data()==
"ADDCHAN") {
1240 if (selAct->data()==
"REMCHAN") {
1244 std::cout<<
"ERROR in VP1TabManager::raiseTabBarContextMenu!!!!!"<<std::endl;
1249 if (
m_d->dontEmitVisibilityChanges)
1252 QSet<IVP1ChannelWidget*> visible;
1253 QSet<IVP1ChannelWidget*> soonvisible;
1254 double soonbonus(0.0);
1260 if (
m_d->fullscreen_dockwidget) {
1262 visible <<
m_d->fullscreen_dockwidget->channelWidget();
1263 }
else if (
m_d->fullscreen_tab) {
1265 assert(
m_d->tab_2_channelwidgets.find(
m_d->fullscreen_tab)!=
m_d->tab_2_channelwidgets.end());
1266 std::set<IVP1ChannelWidget*>::iterator it,itE;
1267 itE =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].end();
1268 for (it =
m_d->tab_2_channelwidgets[
m_d->fullscreen_tab].begin();it!=itE;++it) {
1271 std::cout<<
"fullscreen tab:"<<
m_d->fullscreen_tab<<std::endl;
1276 std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >
::iterator tabIt,tabItE =
m_d->tab_2_channelwidgets.end();
1277 std::set<IVP1ChannelWidget*>::iterator it,itE;
1278 for (tabIt=
m_d->tab_2_channelwidgets.begin();tabIt!=tabItE;++tabIt) {
1280 it = tabIt->second.begin();
1281 itE = tabIt->second.end();
1282 for (;it!=itE;++it) {
1287 if (!
m_d->fullscreen_tab) {
1289 assert(
m_d->channelwidget_2_dockwidget.find(*it)!=
m_d->channelwidget_2_dockwidget.end());
1290 if (
m_d->channelwidget_2_dockwidget[*it]->isFloating())
1302 if (
m_d->fullscreen_dockwidget) {
1303 assert(!
m_d->tabcruisemode);
1307 std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >
::iterator tabIt, tabItE =
m_d->tab_2_channelwidgets.end();
1308 std::set<IVP1ChannelWidget*>::iterator it,itE;
1309 for (tabIt=
m_d->tab_2_channelwidgets.begin();tabIt!=tabItE;++tabIt) {
1311 itE = tabIt->second.end();
1312 for (it=tabIt->second.begin();it!=itE;++it) {
1315 if (*it!=
m_d->fullscreen_dockwidget->channelWidget())
1319 assert(
m_d->channelwidget_2_dockwidget.find(*it)!=
m_d->channelwidget_2_dockwidget.end());
1320 if (
m_d->channelwidget_2_dockwidget[*it]->isFloating())
1325 }
else if (
m_d->fullscreen_tab) {
1326 if (
m_d->tabcruisemode&&
m_d->tab_2_channelwidgets.size()>1) {
1329 QMainWindow * nexttab =
m_d->nextTab();
1331 std::cout<<
"fullscreen tab:"<<
m_d->fullscreen_tab<<std::endl;
1332 std::cout<<
"nexttab:"<<nexttab<<std::endl;
1333 assert(
m_d->tab_2_channelwidgets.find(nexttab)!=
m_d->tab_2_channelwidgets.end());
1334 std::set<IVP1ChannelWidget*>::iterator it,itE=
m_d->tab_2_channelwidgets[nexttab].end();
1335 for(it=
m_d->tab_2_channelwidgets[nexttab].begin();it!=itE;++it){
1342 std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >
::iterator tabIt, tabItE =
m_d->tab_2_channelwidgets.end();
1343 std::set<IVP1ChannelWidget*>::iterator it,itE;
1344 for (tabIt=
m_d->tab_2_channelwidgets.begin();tabIt!=tabItE;++tabIt) {
1346 itE = tabIt->second.end();
1347 for (it=tabIt->second.begin();it!=itE;++it) {
1348 if (
m_d->fullscreen_tab!=tabIt->first&&
currentTab!=tabIt->first) {
1350 assert(
m_d->channelwidget_2_dockwidget.find(*it)!=
m_d->channelwidget_2_dockwidget.end());
1351 if (
m_d->channelwidget_2_dockwidget[*it]->isFloating())
1360 if (
m_d->tabwidget->count()>=2) {
1361 int nexttabindex = (
m_d->tabwidget->currentIndex() + 1) %
m_d->tabwidget->count();
1362 QMainWindow* tab =
static_cast<QMainWindow*
>(
m_d->tabwidget->widget(nexttabindex));
1364 assert(
m_d->tab_2_channelwidgets.find(tab)!=
m_d->tab_2_channelwidgets.end());
1365 std::set<IVP1ChannelWidget*>::iterator it,itE=
m_d->tab_2_channelwidgets[tab].end();
1366 for (it=
m_d->tab_2_channelwidgets[tab].begin();it!=itE;++it) {
1367 assert(
m_d->channelwidget_2_dockwidget.find(*it)!=
m_d->channelwidget_2_dockwidget.end());
1368 if (!
m_d->channelwidget_2_dockwidget[*it]->isFloating())
1375 assert(soonbonus>0.0);
1379 QSet<IVP1ChannelWidget*> tmp = visible;
1380 tmp.intersect(soonvisible);
1381 assert(tmp.empty());
1384 if (visible!=
m_d->lastvisible||soonvisible!=
m_d->lastsoonvisible) {
1385 m_d->lastvisible=visible;
1386 m_d->lastsoonvisible=soonvisible;
1391 if (
m_d->selecteddockwidget) {
1392 if (!visible.contains(
m_d->selecteddockwidget->channelWidget()))
1398 if (visible.count()==1&&(!
m_d->selecteddockwidget||*(visible.begin())!=
m_d->selecteddockwidget->channelWidget())) {
1399 assert(
m_d->channelwidget_2_dockwidget.find(*(visible.begin()))!=
m_d->channelwidget_2_dockwidget.end());
1408 QMainWindow * tab =
m_d->channel2tab(cw);
1410 return "VP1TabManager::channelToTab ERROR: Unknown CW";
1412 std::map<QString,QMainWindow *>::const_iterator it, itE =
m_d->name_2_tab.end();
1413 for ( it =
m_d->name_2_tab.begin(); it!=itE; ++it ) {
1414 if (it->second == tab)
1423 return m_d->name_2_tab.find(tabname)!=
m_d->name_2_tab.end();
1429 std::set<IVP1ChannelWidget*>::const_iterator it2,it2E;
1432 it =
m_d->tab_2_channelwidgets.begin(), itE=
m_d->tab_2_channelwidgets.end();
1433 for (;it!=itE;++it) {
1434 it2=it->second.begin();
1435 it2E=it->second.end();
1436 for (;it2!=it2E;++it2) {
1439 std::map<QString,QMainWindow *>::const_iterator it3,it3E;
1440 it3=
m_d->name_2_tab.begin();it3E=
m_d->name_2_tab.end();
1441 for (;it3!=it3E;++it3) {
1442 if (it3->second==it->first)
1457 QList<IVP1ChannelWidget*> l;
1458 std::map<IVP1ChannelWidget*,VP1DockWidget*>::iterator it, itE(
m_d->channelwidget_2_dockwidget.end());
1459 for(it=
m_d->channelwidget_2_dockwidget.begin();it!=itE;++it) {
1469 return m_d->lastvisible;
1474 return m_d->lastsoonvisible;
1481 return m_d->lastvisible.contains(cw);
1486 if (
m_d->tabcruisemode==b)
1488 bool save =
m_d->dontEmitVisibilityChanges;
1489 m_d->dontEmitVisibilityChanges =
true;
1490 m_d->tabcruisemode = b;
1501 m_d->dontEmitVisibilityChanges=save;
1511 m_d->channelWithPendingRemoval = chnlun;
1518 if (
m_d->channelWithPendingRemoval.isEmpty())
1521 m_d->channelWithPendingRemoval=
"";
1527 QMultiMap<QString,QByteArray> sysstate;
1528 std::set<IVP1System*>::const_iterator it, itE = cw->
systems().end();
1529 for (it=cw->
systems().begin();it!=itE;++it) {
1531 sysstate.insert((*it)->name(),(*it)->saveState());
1534 +
" did not use VP1Serialise in implementation of saveState()");
1538 state.second = sysstate;
1544 if(!state.first.isEmpty())
1547 QList<QString> storedSystems = state.second.keys();
1549 std::set<IVP1System*>::const_iterator itsys, itsysE = cw->
systems().end();
1550 for (itsys=cw->
systems().begin();itsys!=itsysE;++itsys) {
1551 QString name = (*itsys)->name();
1553 QMultiMap<QString,QByteArray>::iterator it_state = state.second.find(name);
1554 if (it_state != state.second.end()) {
1555 storedSystems.removeAll(name);
1566 if (!it_state.value().isEmpty()) {
1568 (*itsys)->restoreFromState(it_state.value());
1571 +
" did not use VP1Deserialise in implementation of restoreFromState()");
1575 std::cout<<
"VP1TabManager::unserializeChannelState Warning: Did not find state data for system "<<name.toStdString()<<std::endl;
1578 for (
const QString& name : storedSystems)
1579 std::cout<<
"VP1TabManager::unserializeChannelState Warning: Did not use stored configuration for system "<<name.toStdString()<<std::endl;
static unsigned numberOfInstantiations()
static void messageVerbose(const QString &)
static void messageDebug(const QString &)
static bool environmentVariableIsOn(const QString &name)
static bool expertSettingIsOn(const QString &type, const QString &name)
static unsigned numberOfInstantiations()
std::map< QString, QMainWindow * > name_2_tab
bool checkTabnameExists(const QString &tabname) const
QMap< QString, QStringList > serializeTabAndChannelConfigInfo() const
QMainWindow * previousTab()
bool checkChannelNameExists(const QString &channelbasename, const bool &isuniquename, const bool &checkfornonexistance=false) const
QMainWindow * fullscreen_tab
bool checkTabnameNotExists(const QString &tabname) const
QStringList channelsInTab(QMainWindow *tab)
std::map< QMainWindow *, std::set< IVP1ChannelWidget * > > tab_2_channelwidgets
Imp(VP1TabManager *tm, VP1TabWidget *tw, VP1ChannelManager *cm)
VP1DockWidget * selecteddockwidget
VP1ChannelManager * channelmanager
QString fullscreen_tabname
QMainWindow * name2tab(const QString &tabname)
QSet< IVP1ChannelWidget * > lastvisible
bool dontEmitVisibilityChanges
std::map< IVP1ChannelWidget *, VP1DockWidget * > channelwidget_2_dockwidget
QString channelWithPendingRemoval
QMainWindow * channel2tab(IVP1ChannelWidget *cw)
VP1DockWidget * fullscreen_dockwidget
QSet< IVP1ChannelWidget * > lastsoonvisible
bool checkTabnameNotEmpty(const QString &tabname) const
std::set< VP1DockWidget * > fullscreen_floatingdocks
IVP1ChannelWidget * fullscreen_channelwidget
VP1TabManager * tabmanager
VP1TabManager(QObject *parent, VP1TabWidget *, VP1ChannelManager *)
void renameTab(const QString &tabname, const QString &newtabname)
void showCurrentTabFullScreen()
QList< IVP1ChannelWidget * > allChannels() const
bool showTab(const QString &)
void currentVisibleChanged()
QPair< QByteArray, QMultiMap< QString, QByteArray > > ChanState
void setSelectedDockWidget(VP1DockWidget *dw=0)
bool isVisible(IVP1ChannelWidget *) const
void serializeChannelState(IVP1ChannelWidget *, ChanState &state)
IVP1ChannelWidget * addChannelToTab(const QString &channelbasename, const QString &tabname)
void unserializeChannelState(IVP1ChannelWidget *cw, ChanState tate)
void loadConfigurationFromFile(const QString &filename, const QMap< QString, QString > &availableplugins)
void setSelectedChannelWidget(IVP1ChannelWidget *cw=0)
void selectedChannelChanged(IVP1ChannelWidget *)
QString suggestNewTabName(const QString &oldtabname) const
void dropOutOfFullScreen()
void cloneChannelToTab(const QString &channeluniquename, const QString &tabname)
void raiseTabBarContextMenu(int, const QPoint &)
void tabListChanged(QStringList)
void removeTab(const QString &tabname)
void setTabCruiseMode(const bool &)
bool showFirstChannelWithGivenBasename(const QString &basename)
void launchStereoEditorCurrentTab()
void moveChannelToTab(const QString &channeluniquename, const QString &tabname)
QString channelToTab(IVP1ChannelWidget *)
const QSet< IVP1ChannelWidget * > & visibleChannels() const
IVP1ChannelWidget * selectedChannelWidget() const
bool eventFilter(QObject *, QEvent *)
QString currentTab() const
void cloneTab(const QString &oldtabname, const QString &newtabname)
void removeChannel(const QString &channeluniquename)
void visibleChannelsChanged(const QSet< IVP1ChannelWidget * > &vis, const QSet< IVP1ChannelWidget * > &soonvis, const double &soonvisbonus)
void executePendingChannelRemoval()
bool hasTab(const QString &) const
QString currentChannelUniqueName() const
void saveConfigurationToFile(const QString &filename, const bool &askonoverride=true)
void showChannelFullScreen(IVP1ChannelWidget *)
const QSet< IVP1ChannelWidget * > & soonVisibleChannels() const
void removeChannelAfterQueueEmpties(const QString &)
void addNewTab(const QString &, const int &index=-1)
void showCurrentChannelFullScreen()
void showTabFullScreen(const QString &tabname)
std::string head(std::string s, const std::string &pattern)
head of a string
std::string basename(std::string name)