Programmable real-time audio signal processing application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmGrScFltk.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. #include <FL/Fl.H>
  2. #include <Fl/fl_draw.h>
  3. #include <FL/Fl_Widget.H>
  4. #include <FL/Fl_Double_Window.H>
  5. #include <Fl/Fl_Output.H>
  6. #include <Fl/Fl_Menu_Bar.H>
  7. #include <vector>
  8. #include "Fl_CbLinker.h"
  9. #include "cmGlobal.h"
  10. #include "cmFloatTypes.h"
  11. #include "cmRpt.h"
  12. #include "cmErr.h"
  13. #include "cmCtx.h"
  14. #include "cmMem.h"
  15. #include "cmMallocDebug.h"
  16. #include "cmLinkedHeap.h"
  17. #include "cmText.h"
  18. #include "cmThread.h"
  19. #include "cmPrefs.h"
  20. #include "cmSymTbl.h"
  21. #include "cmTime.h"
  22. #include "cmMidi.h"
  23. #include "cmMidiFile.h"
  24. #include "cmAudioFile.h"
  25. #include "cmAudioFileMgr.h"
  26. #include "cmTimeLine.h"
  27. #include "cmScore.h"
  28. #include "cmGr.h"
  29. #include "cmGrDevCtx.h"
  30. #include "cmGrPlot.h"
  31. #include "cmGrPage.h"
  32. #include "cmGrFltk.h"
  33. #include "gvHashFunc.h"
  34. #include "cmGrScFltk.h"
  35. #include "cmGrPlotAudio.h"
  36. #include "cmdIf.h"
  37. cmGrScFltk::cmGrScFltk(cmCtx_t* ctx, cmdIf* cp, Fl_Menu_Bar* menu, int x, int y, int w, int h)
  38. : cmGrPlotFltk(ctx,x,y,w,h),
  39. _srate(0),_cmdIf(cp),_menuBar(menu),
  40. _samplesMetricId(cmInvalidId),_secondsMetricId(cmInvalidId),
  41. _objSecs(0),_objId(0),
  42. _togFl(true),
  43. _lastBarPlotObjH(cmGrPlObjNullHandle)
  44. {
  45. cmErrSetup(&_err,&ctx->rpt,"cmGrScFltk");
  46. _createMenu();
  47. if( cmGrPageIsValid(pageHandle()) == false )
  48. return;
  49. initViews(1,1);
  50. unsigned vwIdx = 0;
  51. cmGrPgH_t pgH = pageHandle();
  52. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx);
  53. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  54. cmGrAxH_t axH = cmGrAxNullHandle;
  55. cmGrVExt_t limExt;
  56. _samplesMetricId = cmGrPageLabelFuncRegister( pgH, gvRoundHashValueFunc, this, "Round" );
  57. _secondsMetricId = cmGrPageLabelFuncRegister( pgH, gvMinSecMsHashValueFunc, this, "Min:Sec:Ms" );
  58. unsigned pitchLabelFuncId = cmGrPageLabelFuncRegister( pgH, gvMidiSciPitchValueFunc, this, "Pitch" );
  59. cmGrVExtSetD(&limExt,0,0,0,127);
  60. cmGrObjSetWorldExt( cvH, cmGrRootObjH(cvH), &limExt );
  61. cmGrObjSetWorldLimitExt(cvH, cmGrRootObjH(cvH), &limExt, kTopGrFl | kBottomGrFl );
  62. axH = cmGrViewAxisHandle(vwH, kTopGrIdx);
  63. cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashMarkGrFl | kHashLabelGrFl ));
  64. axH = cmGrViewAxisHandle(vwH, kLeftGrIdx );
  65. cmGrAxisSetLabelFunc( axH, pitchLabelFuncId );
  66. cmGrViewSetLabelFunc( vwH, kLeftGrIdx, pitchLabelFuncId );
  67. axH = cmGrViewAxisHandle(vwH, kRightGrIdx);
  68. cmGrAxisSetCfg( axH, cmClrFlag(cmGrAxisCfg( axH ), kHashLabelGrFl ));
  69. cmGrViewSetCfg( vwH, cmSetFlag(cmGrViewCfg(vwH),kSelectHorzGrFl) );
  70. }
  71. cmGrScFltk::~cmGrScFltk()
  72. {
  73. }
  74. cmScMsgTypeId_t cmGrScFltk::recvScoreMsg( const void* msg, unsigned msgByteCnt )
  75. {
  76. cmScMsg_t m;
  77. cmScoreDecode(msg,msgByteCnt,&m);
  78. switch( m.typeId )
  79. {
  80. case kBeginMsgScId:
  81. {
  82. _objId = 0;
  83. _objSecs = 0;
  84. // remove all objects from all views
  85. //cmGrPageClear(pageHandle());
  86. //_srate = m.srate;
  87. //_updateSeqMenu(m.seqCnt,m.seqId);
  88. }
  89. break;
  90. case kEndMsgScId:
  91. //size(w(),h()+1);
  92. break;
  93. case kEventMsgScId:
  94. _insertEvent(&m.u.evt);
  95. break;
  96. case kSectionMsgScId:
  97. _insertSection(&m.u.sect);
  98. break;
  99. case kVarMsgScId:
  100. break;
  101. default:
  102. { assert(0); }
  103. }
  104. return m.typeId;
  105. }
  106. void cmGrScFltk::setSampleRate( double srate )
  107. { _srate = srate; }
  108. double cmGrScFltk::sampleRate() const
  109. { return _srate; }
  110. bool cmGrScFltk::on_plot_object( cmGrPlotCbArg_t* arg )
  111. {
  112. if( arg->selId==kStateChangeGrPlId && cmIsFlag(arg->deltaFlags,kSelectGrPlFl) )
  113. {
  114. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(arg->objH);
  115. if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep != NULL /* && sep->type == kBarEvtScId */ )
  116. {
  117. _lastBarPlotObjH = arg->objH;
  118. unsigned scoreIdx = scoreSelectedEleIndex();
  119. // callback to: kcApp::_ctl_cb(ctl_t* cp)
  120. callback()(this,user_data());
  121. _cmdIf->onScoreBarSelected(scoreIdx);
  122. setStatusText(cmTsPrintfS("Score Index:%i",scoreIdx));
  123. }
  124. }
  125. return true;
  126. }
  127. void cmGrScFltk::selectBar( unsigned barNumb )
  128. {
  129. cmGrPlH_t plH = plotHandle();
  130. unsigned n = cmGrPlotObjectCount(plH);
  131. unsigned i;
  132. for(i=0; i<n; ++i)
  133. {
  134. cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
  135. if( cmGrPlotObjIsValid(poH) )
  136. {
  137. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
  138. if( sop->id==kEventMsgScId && sop->u.ep!=NULL && sop->u.ep->type==kBarEvtScId && sop->u.ep->barNumb==barNumb )
  139. {
  140. unsigned flags = cmGrPlotObjStateFlags(poH);
  141. cmGrPlotObjSetStateFlags(poH,cmSetFlag(flags,kFocusGrPlFl | kSelectGrPlFl));
  142. redraw();
  143. _lastBarPlotObjH = poH;
  144. _cmdIf->onScoreBarSelected(sop->u.ep->locIdx);
  145. setStatusText(cmTsPrintfS("Score Index:%i",sop->u.ep->locIdx));
  146. break;
  147. }
  148. }
  149. }
  150. }
  151. unsigned cmGrScFltk::scoreSelectedEleIndex() const
  152. {
  153. if( cmGrPlotObjIsValid(_lastBarPlotObjH) )
  154. {
  155. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(_lastBarPlotObjH);
  156. if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep != NULL /* && sop->u.ep->type == kBarEvtScId */ )
  157. return sop->u.ep->locIdx;
  158. }
  159. return cmInvalidIdx;
  160. }
  161. void cmGrScFltk::setScoreLocation( unsigned locIdx, unsigned vel, unsigned smpIdx )
  162. {
  163. }
  164. void cmGrScFltk::_insertSection( const cmScoreSection_t* m )
  165. {
  166. // The argument is a serialzed copy of a cmScoreSection_t record.
  167. // Convert it to a pointer to an actual object in the local score mgr.
  168. if( cmGrPageIsValid(pageHandle()) == false )
  169. return;
  170. m = _cmdIf->scoreSectionIdToPtr(m->index);
  171. assert(m!=NULL);
  172. const cmScoreEvt_t* ep = _cmdIf->scoreEventIdToPtr(m->begEvtIndex);
  173. assert( ep != NULL );
  174. cmGrPlH_t plH = plotHandle();
  175. cmGrPgH_t pgH = pageHandle();
  176. unsigned vwIdx = 0;
  177. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx );
  178. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  179. cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle;
  180. cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle;
  181. cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle;
  182. cmGrPlObjH_t objH = cmGrPlObjNullHandle;
  183. cmGrPlObjTypeId_t objTypeId = kLineGrPlId;
  184. cmReal_t x = ep->secs;
  185. cmReal_t y = 120;
  186. cmReal_t w = 0;
  187. cmReal_t h = 7;
  188. const cmChar_t* label = m->label;
  189. unsigned flags = kNoDragGrPlFl;
  190. cmGrVExt_t wext;
  191. scObj_t scObj(m);
  192. cmGrVExtSetNull(&wext);
  193. if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC )
  194. {
  195. cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score section.", cmStringNullGuard(label));
  196. return;
  197. }
  198. cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj));
  199. unsigned f = 0 ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl);
  200. cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlackGrId );
  201. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kGreenGrId );
  202. //cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 );
  203. cmGrPlotObjSetFontSize(objH,8);
  204. }
  205. void cmGrScFltk::_insertEvent( const cmScoreEvt_t* m )
  206. {
  207. // The argument is a serialzed copy of a cmScoreEvt record.
  208. // Convert it to a pointer to an actual object in the local score mgr.
  209. if( cmGrPageIsValid(pageHandle()) == false )
  210. return;
  211. m = _cmdIf->scoreEventIdToPtr(m->index);
  212. assert(m!=NULL);
  213. cmGrPlH_t plH = plotHandle();
  214. cmGrPgH_t pgH = pageHandle();
  215. unsigned vwIdx = 0;
  216. cmGrVwH_t vwH = cmGrPageViewHandle( pgH, vwIdx );
  217. cmGrH_t cvH = cmGrViewGrHandle( vwH );
  218. cmGrPlObjH_t parentObjH = cmGrPlObjNullHandle;
  219. cmGrPlObjH_t xAnchorObjH = cmGrPlObjNullHandle;
  220. cmGrPlObjH_t yAnchorObjH = cmGrPlObjNullHandle;
  221. cmGrPlObjH_t objH = cmGrPlObjNullHandle;
  222. cmGrPlObjTypeId_t objTypeId = kVLineGrPlId;
  223. cmReal_t x = m->secs;
  224. cmReal_t y = 0;
  225. cmReal_t w = 0;
  226. cmReal_t h = 127;
  227. const cmChar_t* label = NULL;
  228. unsigned flags = kNoDragGrPlFl;
  229. int bufN = 7;
  230. cmChar_t buf[bufN+1];
  231. cmGrVExt_t wext;
  232. scObj_t scObj(m);
  233. cmGrVExtSetNull(&wext);
  234. switch( m->type )
  235. {
  236. case kNonEvtScId:
  237. objTypeId = kRectGrPlId;
  238. y = m->pitch;
  239. h = 1;
  240. w = m->durSecs;
  241. label = cmMidiToSciPitch(m->pitch,NULL,0);
  242. break;
  243. case kBarEvtScId:
  244. {
  245. buf[bufN] = 0;
  246. snprintf(buf,bufN,"%i",m->barNumb);
  247. objTypeId = kVLineGrPlId;
  248. label = buf;
  249. }
  250. break;
  251. case kPedalEvtScId:
  252. if( cmIsFlag(m->flags, kPedalDnScFl ) == false )
  253. return;
  254. objTypeId = kRectGrPlId;
  255. y = m->pitch; // pedal type (damper=64, sostenuto=66) is held in pitch
  256. h = 1;
  257. w = m->durSecs;
  258. flags += kNoFillGrPlFl;
  259. break;
  260. default:
  261. return;
  262. }
  263. if( cmGrPlotObjCreate(plH, cvH, &objH, _objId++, parentObjH, xAnchorObjH, yAnchorObjH, objTypeId, flags, x, y, w, h, label, cmGrVExtIsNull(&wext)?NULL:&wext ) != kOkGrPlRC )
  264. {
  265. cmErrMsg(&_err,kInsertObjFailRC,"Insert failed on a score event.", cmStringNullGuard(label));
  266. return;
  267. }
  268. cmGrPlotObjAllocUser(objH,&scObj,sizeof(scObj));
  269. switch( m->type )
  270. {
  271. case kBarEvtScId:
  272. {
  273. unsigned f = _togFl ? (kNorthJsGrFl | kTopJsGrFl) : (kSouthJsGrFl | kBottomJsGrFl);
  274. cmGrPlotObjSetLabelAttr( objH, f | kWestJsGrFl | kTopJsGrFl | kRightJsGrFl, 0, kBlueGrId );
  275. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, kYellowGrId );
  276. cmGrPlotObjSetPhysExt(objH, 1, 0, 1, 0 );
  277. _togFl = !_togFl;
  278. }
  279. break;
  280. case kNonEvtScId:
  281. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, cmGrPlotObjFillColor(objH,kEnablePlGrId) );
  282. cmGrPlotObjSetFontSize(objH,8);
  283. break;
  284. case kPedalEvtScId:
  285. cmGrPlotObjSetLineColor( objH, kEnablePlGrId, y==64 ? kDarkGreenGrId : kLightGreenGrId );
  286. break;
  287. default:
  288. break;
  289. }
  290. if( cmIsFlag(m->flags,kInvalidScFl) )
  291. {
  292. cmGrPlotObjSetFillColor(objH, kEnablePlGrId, kRedGrId );
  293. }
  294. }
  295. void cmGrScFltk::_createMenu( )
  296. {
  297. int idx = _menuBar->add("Score",0,NULL,0,FL_SUBMENU);
  298. const char* titleArray[] = { "Pitch", "Attributes", "Dynamics", "Location", "Fraction", "Section Even", "Section Dyn", "Section Tempo" };
  299. bool onFl[] = { true, false, false, false, false, false, false, false };
  300. int i;
  301. for(i=0; i<kMenuItemCnt; ++i)
  302. {
  303. _menuArray[i].id = i;
  304. _menuArray[i].p = this;
  305. _menuBar->insert(idx+1+i,titleArray[i],0,_s_menuCallback, _menuArray + i, FL_MENU_TOGGLE );
  306. if( onFl[i] )
  307. {
  308. Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + idx + i + 1;
  309. mip->set();
  310. }
  311. }
  312. }
  313. bool cmGrScFltk::_isMenuChecked( int id )
  314. {
  315. unsigned i;
  316. // locate the menu item assoc'd with id
  317. for(i=0; i<kMenuItemCnt; ++i)
  318. if( _menuArray[i].id == id )
  319. break;
  320. assert( i < kMenuItemCnt );
  321. int menuIdx;
  322. if(( menuIdx = _menuBar->find_index("Score")) == -1 )
  323. return false;
  324. // The menu items and _menuArray[] were initialized in the same order
  325. // therefore the offset from the base of both should be the same.
  326. Fl_Menu_Item* mip = (Fl_Menu_Item*)_menuBar->menu() + menuIdx + i + 1;
  327. assert( (item_t*)mip->user_data() == _menuArray + i );
  328. return mip->value() != 0;
  329. }
  330. void cmGrScFltk::_setEventLabels()
  331. {
  332. enum { kPitchFl=0x01, kAttrFl=0x02, kDynFl=0x04, kLocFl=0x08, kFracFl=0x10 };
  333. cmGrPlH_t plH = plotHandle();
  334. unsigned flags = 0;
  335. flags |= _isMenuChecked(kPitchMId) ? kPitchFl : 0;
  336. flags |= _isMenuChecked(kAttrMId) ? kAttrFl : 0;
  337. flags |= _isMenuChecked(kDynMId) ? kDynFl : 0;
  338. flags |= _isMenuChecked(kLocIdxMId) ? kLocFl : 0;
  339. flags |= _isMenuChecked(kFracMId) ? kFracFl : 0;
  340. unsigned n = cmGrPlotObjectCount(plH);
  341. unsigned i;
  342. for(i=0; i<n; ++i)
  343. {
  344. cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
  345. if( cmGrPlotObjIsValid(poH) )
  346. {
  347. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
  348. if( sop!=NULL && sop->id==kEventMsgScId && sop->u.ep!=NULL && sop->u.ep->type==kNonEvtScId )
  349. {
  350. const cmScoreEvt_t* ep = sop->u.ep;
  351. int bufN = 255;
  352. cmChar_t buf[ bufN+1 ];
  353. buf[bufN] = 0;
  354. buf[0] = 0;
  355. if( cmIsFlag(flags,kPitchFl) )
  356. snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",cmMidiToSciPitch(ep->pitch,NULL,0));
  357. if( cmIsFlag(flags,kAttrFl) )
  358. {
  359. cmChar_t s[4];
  360. int j=0;
  361. if( cmIsFlag(ep->flags,kEvenScFl) )
  362. s[j++] = 'e';
  363. if( cmIsFlag(ep->flags,kDynScFl) )
  364. s[j++] = 'd';
  365. if( cmIsFlag(ep->flags,kTempoScFl) )
  366. s[j++] = 't';
  367. s[j] = 0;
  368. snprintf(buf+strlen(buf),bufN-strlen(buf),"%s ",s);
  369. }
  370. if( cmIsFlag(flags,kDynFl) && cmIsFlag(ep->flags,kDynScFl) )
  371. {
  372. snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%i",ep->dynVal);
  373. if( ep->perfDynLvl != 0 )
  374. snprintf(buf+strlen(buf),bufN-strlen(buf),"|%i ",ep->perfDynLvl);
  375. else
  376. snprintf(buf+strlen(buf),bufN-strlen(buf)," ");
  377. }
  378. if( cmIsFlag(flags,kLocFl) )
  379. snprintf(buf+strlen(buf),bufN-strlen(buf),"loc:%i ",ep->locIdx);
  380. if( cmIsFlag(flags,kFracFl) && ep->frac != 0)
  381. snprintf(buf+strlen(buf),bufN-strlen(buf),"%5.3f ",ep->frac);
  382. cmGrPlotObjSetLabel(poH, buf );
  383. }
  384. }
  385. }
  386. }
  387. void cmGrScFltk::_setSectionLabels()
  388. {
  389. enum { kEvenFl=0x01, kDynFl=0x02, kTempoFl=0x04 };
  390. cmGrPlH_t plH = plotHandle();
  391. unsigned flags = 0;
  392. flags |= _isMenuChecked(kSectEvenMId) ? kEvenFl : 0;
  393. flags |= _isMenuChecked(kSectDynMId) ? kDynFl : 0;
  394. flags |= _isMenuChecked(kSectTempoMId) ? kTempoFl : 0;
  395. unsigned n = cmGrPlotObjectCount(plH);
  396. unsigned i;
  397. for(i=0; i<n; ++i)
  398. {
  399. cmGrPlObjH_t poH = cmGrPlotObjectIndexToHandle(plH,i);
  400. if( cmGrPlotObjIsValid(poH) )
  401. {
  402. scObj_t* sop = (scObj_t*)cmGrPlotObjUserPtr(poH);
  403. if( sop!=NULL && sop->id==kSectionMsgScId && sop->u.sp!=NULL )
  404. {
  405. const cmScoreSection_t* sp = sop->u.sp;
  406. int bufN = 255;
  407. cmChar_t buf[ bufN+1 ];
  408. buf[bufN] = 0;
  409. buf[0] = 0;
  410. snprintf(buf,bufN,"%s ",sp->label);
  411. if( cmIsFlag(flags,kEvenFl) && sp->vars[kEvenVarScId] != DBL_MAX)
  412. snprintf(buf+strlen(buf),bufN-strlen(buf),"e:%f ",sp->vars[kEvenVarScId]);
  413. if( cmIsFlag(flags,kDynFl) && sp->vars[kDynVarScId] != DBL_MAX)
  414. snprintf(buf+strlen(buf),bufN-strlen(buf),"d:%f ",sp->vars[kDynVarScId]);
  415. if( cmIsFlag(flags,kTempoFl) && sp->vars[kTempoVarScId] != DBL_MAX)
  416. snprintf(buf+strlen(buf),bufN-strlen(buf),"t:%f ",sp->vars[kTempoVarScId]);
  417. cmGrPlotObjSetLabel(poH, buf );
  418. }
  419. }
  420. }
  421. }
  422. void cmGrScFltk::_s_menuCallback(Fl_Widget* w, void* arg )
  423. {
  424. item_t* ip = (item_t*)arg;
  425. cmGrScFltk* p = ip->p;
  426. unsigned long id = ip->id;
  427. switch( id )
  428. {
  429. case kPitchMId:
  430. case kAttrMId:
  431. case kDynMId:
  432. case kLocIdxMId:
  433. case kFracMId:
  434. {
  435. p->_setEventLabels();
  436. p->redraw();
  437. }
  438. break;
  439. case kSectEvenMId:
  440. case kSectDynMId:
  441. case kSectTempoMId:
  442. {
  443. p->_setSectionLabels();
  444. p->redraw();
  445. }
  446. break;
  447. }
  448. }