37 #include <QMessageBox>
40 #include <QMainWindow>
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;
162 QMessageBox::critical(0,
"Error - Tab "+tabname+
" does not exists",
163 "Tab <i>"+tabname+
"</i> does not exists.",QMessageBox::Ok,QMessageBox::Ok);
171 if (!checkTabnameNotEmpty(tabname))
173 if (name_2_tab.find(tabname)!=name_2_tab.end()) {
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)
199 : channelmanager->baseNameExists(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);
211 assert(tab_2_channelwidgets.find(tab)!=tab_2_channelwidgets.end());
212 if (tab_2_channelwidgets.find(tab)==tab_2_channelwidgets.end())
213 return QStringList();
214 std::set<IVP1ChannelWidget*>::const_iterator
it,
itE = tab_2_channelwidgets[tab].end();
218 l << (*it)->unique_name();
228 assert(name_2_tab.find(tabname)!=name_2_tab.end());
229 if (name_2_tab.find(tabname)==name_2_tab.end())
230 return QStringList();
231 return channelsInTab(name_2_tab[tabname]);
242 QMainWindow *
t =
new QMainWindow();
243 t->setDockNestingEnabled(
true);
264 qApp->removeEventFilter(
this);
265 QWidget * focuswidget = qApp->focusWidget();
287 dock->setFeatures(VP1DockWidget::DockWidgetMovable|VP1DockWidget::DockWidgetFloatable);
289 dock->setFloating(
true);
296 if (focuswidget&&!focuswidget->hasFocus())
297 focuswidget->setFocus(Qt::OtherFocusReason);
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)
369 cw->showFullScreen();
370 qApp->installEventFilter(
this);
426 if (dock->isFloating()) {
428 dock->setFloating(
false);
430 dock->setFeatures(VP1DockWidget::DockWidgetMovable);
448 qApp->installEventFilter(
this);
472 #if defined BUILDVP1LIGHT
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);
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);
503 cw->setUpdatesEnabled(
false);
511 tab->addDockWidget(Qt::TopDockWidgetArea, dock);
517 cw->setUpdatesEnabled(
true);
533 assert(tabindex!=-1);
566 (*it)->setUpdatesEnabled(
false);
593 for(
const QString& tab :
tabList() ) {
614 cw->setUpdatesEnabled(
false);
631 tab->setUpdatesEnabled(
false);
632 tab->removeDockWidget(dw);
649 tab->setUpdatesEnabled(
true);
662 std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >
::iterator it = tab_2_channelwidgets.begin();
663 std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >
::iterator itE = tab_2_channelwidgets.end();
665 if (
it->second.find(cw)!=
it->second.end())
675 if (name_2_tab.find(tabname)==name_2_tab.end())
677 return name_2_tab[tabname];
700 if (tab_old==tab_new)
703 tab_old->removeDockWidget(dw);
704 dw->setParent(tab_new);
705 tab_new->addDockWidget(Qt::TopDockWidgetArea, dw);
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);
769 QMessageBox::critical(0,
"Error - Empty file name provided",
770 "Empty file name provided.",QMessageBox::Ok,QMessageBox::Ok);
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)
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;
805 QByteArray byteArray;
806 QBuffer
buffer(&byteArray);
807 buffer.open(QIODevice::WriteOnly);
809 out<<QString(
"This is an automatically generated config file for VP1. [cfg version 003]" );
812 out<<tab2arrangements;
814 out<<QString(
"This is the end of the automatically generated config file for VP1." );
818 outfile<<qCompress(byteArray).toBase64();
826 QMessageBox::critical(0,
"Error - Empty file name provided",
827 "Empty file name provided.",QMessageBox::Ok,QMessageBox::Ok);
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);
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;
860 QByteArray byteArray = qUncompress(QByteArray::fromBase64(byteArray64));
862 QBuffer
buffer(&byteArray);
863 buffer.open(QIODevice::ReadOnly);
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];
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);
955 lastaddedtab=newtabname;
957 QMapIterator<QString,ChanState>
it( tab2channels.value(newtabname_infile) );
959 while (
it.hasNext()) {
964 channelsFailureMsg +=
it.key()+
" (tab "+newtabname+
")"+
"\n";
970 channelsFailureMsg +=
it.key()+
" (tab "+newtabname+
")"+
"\n";
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);
1007 assert(name_2_tab.find(tabname)!=name_2_tab.end());
1008 QMainWindow * tab = name_2_tab.find(tabname)->second;
1009 QMultiMap<QString,ChanState> channelsinfo;
1010 std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::const_iterator itcws=tab_2_channelwidgets.find(tab);
1011 assert(itcws!=tab_2_channelwidgets.end());
1012 std::set<IVP1ChannelWidget*>::const_iterator
it = itcws->second.begin();
1013 std::set<IVP1ChannelWidget*>::const_iterator
itE = itcws->second.end();
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;
1049 if (tabwidget->count()<=1)
1051 std::cout<<
"currentindex:"<<tabwidget->currentIndex()<<std::endl;
1052 std::cout<<
"nextindex:"<<(tabwidget->currentIndex() + 1) % tabwidget->count()<<std::endl;
1053 std::cout<<
"ntabs:"<<tab_2_channelwidgets.size()<<std::endl;
1054 QMainWindow*nexttab=
static_cast<QMainWindow*
>(tabwidget->widget((tabwidget->currentIndex() + 1) % tabwidget->count()));
1056 assert(tab_2_channelwidgets.find(nexttab)!=tab_2_channelwidgets.end());
1065 if (tabwidget->count()<=1)
1067 int newindex = tabwidget->currentIndex() - 1;
1069 newindex += tabwidget->count();
1070 QMainWindow*prevtab =
static_cast<QMainWindow*
>(tabwidget->widget(newindex % tabwidget->count()));
1071 if (tab_2_channelwidgets.find(prevtab)==tab_2_channelwidgets.end())
1072 return fullscreen_tab;
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");
1158 if (chnls.empty()) {
1159 menu_addchan.addAction(
"No channels available")->setEnabled(
false);
1161 for (
const QString& chnl : chnls) {
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);
1173 if (chnls_rem.empty())
1174 pFullScreenAction->setEnabled(
false);
1176 if (chnls_rem.empty()) {
1177 menu_remchan.addAction(
"No channels in tab")->setEnabled(
false);
1179 for (
const QString& chnl : chnls_rem) {
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;
1252 QSet<IVP1ChannelWidget*> visible;
1253 QSet<IVP1ChannelWidget*> soonvisible;
1254 double soonbonus(0.0);
1280 it = tabIt->second.begin();
1281 itE = tabIt->second.end();
1311 itE = tabIt->second.end();
1312 for (
it=tabIt->second.begin();
it!=
itE;++
it) {
1332 std::cout<<
"nexttab:"<<nexttab<<std::endl;
1346 itE = tabIt->second.end();
1347 for (
it=tabIt->second.begin();
it!=
itE;++
it) {
1362 QMainWindow* tab =
static_cast<QMainWindow*
>(
m_d->
tabwidget->widget(nexttabindex));
1375 assert(soonbonus>0.0);
1379 QSet<IVP1ChannelWidget*>
tmp = visible;
1380 tmp.intersect(soonvisible);
1381 assert(
tmp.empty());
1410 return "VP1TabManager::channelToTab ERROR: Unknown CW";
1414 if (
it->second == tab)
1429 std::set<IVP1ChannelWidget*>::const_iterator it2,it2E;
1431 std::map<QMainWindow*,std::set<IVP1ChannelWidget*> >::const_iterator
1434 it2=
it->second.begin();
1435 it2E=
it->second.end();
1436 for (;it2!=it2E;++it2) {
1439 std::map<QString,QMainWindow *>::const_iterator it3,it3E;
1441 for (;it3!=it3E;++it3) {
1442 if (it3->second==
it->first)
1457 QList<IVP1ChannelWidget*>
l;
1527 QMultiMap<QString,QByteArray> sysstate;
1528 std::set<IVP1System*>::const_iterator
it,
itE = cw->
systems().end();
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();
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;