comparison framework/MainWindowBase.cpp @ 404:08a45e4cf1b1 tonioni

Update subrepos and merge from default branch
author Chris Cannam
date Tue, 02 Sep 2014 16:23:48 +0100
parents eb84b06301da
children 41242512d544
comparison
equal deleted inserted replaced
384:ad33fdc4ad92 404:08a45e4cf1b1
153 m_abandoning(false), 153 m_abandoning(false),
154 m_labeller(0), 154 m_labeller(0),
155 m_lastPlayStatusSec(0), 155 m_lastPlayStatusSec(0),
156 m_initialDarkBackground(false), 156 m_initialDarkBackground(false),
157 m_defaultFfwdRwdStep(2, 0), 157 m_defaultFfwdRwdStep(2, 0),
158 m_statusLabel(0) 158 m_statusLabel(0),
159 m_menuShortcutMapper(0)
159 { 160 {
160 Profiler profiler("MainWindowBase::MainWindowBase"); 161 Profiler profiler("MainWindowBase::MainWindowBase");
161 162
162 #ifdef Q_WS_X11 163 #ifdef Q_WS_X11
163 XSetErrorHandler(handle_x11_error); 164 XSetErrorHandler(handle_x11_error);
274 } 275 }
275 276
276 void 277 void
277 MainWindowBase::finaliseMenus() 278 MainWindowBase::finaliseMenus()
278 { 279 {
280 delete m_menuShortcutMapper;
281 m_menuShortcutMapper = 0;
282
283 foreach (QShortcut *sc, m_appShortcuts) {
284 delete sc;
285 }
286 m_appShortcuts.clear();
287
279 QMenuBar *mb = menuBar(); 288 QMenuBar *mb = menuBar();
280 QList<QMenu *> menus = mb->findChildren<QMenu *>(); 289
290 // This used to find all children of QMenu type, and call
291 // finaliseMenu on those. But it seems we are getting hold of some
292 // menus that way that are not actually active in the menu bar and
293 // are not returned in their parent menu's actions() list, and if
294 // we finalise those, we end up with duplicate shortcuts in the
295 // app shortcut mapper. So we should do this by descending the
296 // menu tree through only those menus accessible via actions()
297 // from their parents instead.
298
299 QList<QMenu *> menus = mb->findChildren<QMenu *>
300 (QString(), Qt::FindDirectChildrenOnly);
301
281 foreach (QMenu *menu, menus) { 302 foreach (QMenu *menu, menus) {
282 if (menu) finaliseMenu(menu); 303 if (menu) finaliseMenu(menu);
283 } 304 }
284 } 305 }
285 306
321 // i.e. that will not otherwise work. The downside is that if this 342 // i.e. that will not otherwise work. The downside is that if this
322 // bug is fixed in a future Qt release, we will start getting 343 // bug is fixed in a future Qt release, we will start getting
323 // "ambiguous shortcut" errors from the menu entry actions and 344 // "ambiguous shortcut" errors from the menu entry actions and
324 // will need to update the code.) 345 // will need to update the code.)
325 346
326 QSignalMapper *mapper = new QSignalMapper(this); 347 if (!m_menuShortcutMapper) {
327 348 m_menuShortcutMapper = new QSignalMapper(this);
328 connect(mapper, SIGNAL(mapped(QObject *)), 349 connect(m_menuShortcutMapper, SIGNAL(mapped(QObject *)),
329 this, SLOT(menuActionMapperInvoked(QObject *))); 350 this, SLOT(menuActionMapperInvoked(QObject *)));
351 }
330 352
331 foreach (QAction *a, menu->actions()) { 353 foreach (QAction *a, menu->actions()) {
332 QWidgetList ww = a->associatedWidgets(); 354
333 bool hasButton = false; 355 if (a->isSeparator()) {
334 foreach (QWidget *w, ww) { 356 continue;
335 if (qobject_cast<QAbstractButton *>(w)) { 357 } else if (a->menu()) {
336 hasButton = true; 358 finaliseMenu(a->menu());
337 break; 359 } else {
360
361 QWidgetList ww = a->associatedWidgets();
362 bool hasButton = false;
363 foreach (QWidget *w, ww) {
364 if (qobject_cast<QAbstractButton *>(w)) {
365 hasButton = true;
366 break;
367 }
338 } 368 }
339 } 369 if (hasButton) continue;
340 if (hasButton) continue; 370 QKeySequence sc = a->shortcut();
341 QKeySequence sc = a->shortcut(); 371
342 if (sc.count() == 1 && !(sc[0] & Qt::KeyboardModifierMask)) { 372 // Note that the set of "single-key shortcuts" that aren't
343 QShortcut *newSc = new QShortcut(sc, a->parentWidget()); 373 // working and that we need to handle here includes those
344 QObject::connect(newSc, SIGNAL(activated()), mapper, SLOT(map())); 374 // with the Shift modifier mask as well as those with no
345 mapper->setMapping(newSc, a); 375 // modifier at all
376 if (sc.count() == 1 &&
377 ((sc[0] & Qt::KeyboardModifierMask) == Qt::NoModifier ||
378 (sc[0] & Qt::KeyboardModifierMask) == Qt::ShiftModifier)) {
379 QShortcut *newSc = new QShortcut(sc, a->parentWidget());
380 QObject::connect(newSc, SIGNAL(activated()),
381 m_menuShortcutMapper, SLOT(map()));
382 m_menuShortcutMapper->setMapping(newSc, a);
383 m_appShortcuts.push_back(newSc);
384 }
346 } 385 }
347 } 386 }
348 #endif 387 #endif
349 } 388 }
350 389
468 if (i > 0) havePrevPane = true; 507 if (i > 0) havePrevPane = true;
469 if (i < m_paneStack->getPaneCount()-1) haveNextPane = true; 508 if (i < m_paneStack->getPaneCount()-1) haveNextPane = true;
470 break; 509 break;
471 } 510 }
472 } 511 }
473 if (currentLayer) { 512 // the prev/next layer commands actually include the pane
474 for (int i = 0; i < currentPane->getLayerCount(); ++i) { 513 // itself as one of the selectables -- so we always have a
475 if (currentPane->getLayer(i) == currentLayer) { 514 // prev and next layer, as long as we have a pane with at
476 if (i > 0) havePrevLayer = true; 515 // least one layer in it
477 if (i < currentPane->getLayerCount()-1) haveNextLayer = true; 516 if (currentPane->getLayerCount() > 0) {
478 break; 517 havePrevLayer = true;
479 } 518 haveNextLayer = true;
480 }
481 } 519 }
482 } 520 }
483 521
484 bool haveCurrentPane = 522 bool haveCurrentPane =
485 (currentPane != 0); 523 (currentPane != 0);
652 // frame before switching to whichever one we decide we want to 690 // frame before switching to whichever one we decide we want to
653 // switch to, regardless of our efforts. 691 // switch to, regardless of our efforts.
654 692
655 int frame = m_playSource->getCurrentBufferedFrame(); 693 int frame = m_playSource->getCurrentBufferedFrame();
656 694
657 // cerr << "currentPaneChanged: current frame (in ref model) = " << frame << endl; 695 cerr << "currentPaneChanged: current frame (in ref model) = " << frame << endl;
658 696
659 View::ModelSet soloModels = p->getModels(); 697 View::ModelSet soloModels = p->getModels();
660 698
661 View::ModelSet sources; 699 View::ModelSet sources;
662 for (View::ModelSet::iterator mi = soloModels.begin(); 700 for (View::ModelSet::iterator mi = soloModels.begin();
1218 1256
1219 MainWindowBase::FileOpenStatus 1257 MainWindowBase::FileOpenStatus
1220 MainWindowBase::openAudio(FileSource source, AudioFileOpenMode mode, 1258 MainWindowBase::openAudio(FileSource source, AudioFileOpenMode mode,
1221 QString templateName) 1259 QString templateName)
1222 { 1260 {
1223 SVDEBUG << "MainWindowBase::openAudio(" << source.getLocation() << ")" << endl; 1261 SVDEBUG << "MainWindowBase::openAudio(" << source.getLocation() << ") with mode " << mode << " and template " << templateName << endl;
1224 1262
1225 if (templateName == "") { 1263 if (templateName == "") {
1226 templateName = getDefaultSessionTemplate(); 1264 templateName = getDefaultSessionTemplate();
1227 } 1265 }
1228 1266
1315 mode = CreateAdditionalModel; 1353 mode = CreateAdditionalModel;
1316 } 1354 }
1317 } 1355 }
1318 1356
1319 if (mode == CreateAdditionalModel && !getMainModel()) { 1357 if (mode == CreateAdditionalModel && !getMainModel()) {
1358 SVDEBUG << "Mode is CreateAdditionalModel but we have no main model, switching to ReplaceSession mode" << endl;
1320 mode = ReplaceSession; 1359 mode = ReplaceSession;
1321 } 1360 }
1322 1361
1323 bool loadedTemplate = false; 1362 bool loadedTemplate = false;
1324 1363
1325 if (mode == ReplaceSession) { 1364 if (mode == ReplaceSession) {
1326 1365
1327 if (!checkSaveModified()) return FileOpenCancelled; 1366 if (!checkSaveModified()) return FileOpenCancelled;
1328 1367
1329 cerr << "SV looking for template " << templateName << endl; 1368 SVDEBUG << "SV looking for template " << templateName << endl;
1330 if (templateName != "") { 1369 if (templateName != "") {
1331 FileOpenStatus tplStatus = openSessionTemplate(templateName); 1370 FileOpenStatus tplStatus = openSessionTemplate(templateName);
1332 if (tplStatus == FileOpenCancelled) { 1371 if (tplStatus == FileOpenCancelled) {
1333 cerr << "Template load cancelled" << endl; 1372 cerr << "Template load cancelled" << endl;
1334 return FileOpenCancelled; 1373 return FileOpenCancelled;
1338 loadedTemplate = true; 1377 loadedTemplate = true;
1339 } 1378 }
1340 } 1379 }
1341 1380
1342 if (!loadedTemplate) { 1381 if (!loadedTemplate) {
1382 SVDEBUG << "No template found: closing session, creating new empty document" << endl;
1343 closeSession(); 1383 closeSession();
1344 createDocument(); 1384 createDocument();
1345 } 1385 }
1346 1386
1387 SVDEBUG << "Now switching to ReplaceMainModel mode" << endl;
1347 mode = ReplaceMainModel; 1388 mode = ReplaceMainModel;
1348 } 1389 }
1349 1390
1350 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation())); 1391 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation()));
1351 1392
3008 } 3049 }
3009 3050
3010 void 3051 void
3011 MainWindowBase::previousLayer() 3052 MainWindowBase::previousLayer()
3012 { 3053 {
3013 //!!! Not right -- pane lists layers in stacking order
3014
3015 if (!m_paneStack) return; 3054 if (!m_paneStack) return;
3016 3055
3017 Pane *currentPane = m_paneStack->getCurrentPane(); 3056 Pane *currentPane = m_paneStack->getCurrentPane();
3018 if (!currentPane) return; 3057 if (!currentPane) return;
3019 3058
3059 int count = currentPane->getLayerCount();
3060 if (count == 0) return;
3061
3020 Layer *currentLayer = currentPane->getSelectedLayer(); 3062 Layer *currentLayer = currentPane->getSelectedLayer();
3021 if (!currentLayer) return; 3063
3022 3064 if (!currentLayer) {
3023 for (int i = 0; i < currentPane->getLayerCount(); ++i) { 3065 // The pane itself is current
3024 if (currentPane->getLayer(i) == currentLayer) { 3066 m_paneStack->setCurrentLayer
3025 if (i == 0) return; 3067 (currentPane, currentPane->getFixedOrderLayer(count-1));
3026 m_paneStack->setCurrentLayer(currentPane, 3068 } else {
3027 currentPane->getLayer(i-1)); 3069 for (int i = 0; i < count; ++i) {
3028 updateMenuStates(); 3070 if (currentPane->getFixedOrderLayer(i) == currentLayer) {
3029 return; 3071 if (i == 0) {
3030 } 3072 m_paneStack->setCurrentLayer
3031 } 3073 (currentPane, 0); // pane
3074 } else {
3075 m_paneStack->setCurrentLayer
3076 (currentPane, currentPane->getFixedOrderLayer(i-1));
3077 }
3078 break;
3079 }
3080 }
3081 }
3082
3083 updateMenuStates();
3032 } 3084 }
3033 3085
3034 void 3086 void
3035 MainWindowBase::nextLayer() 3087 MainWindowBase::nextLayer()
3036 { 3088 {
3037 //!!! Not right -- pane lists layers in stacking order
3038
3039 if (!m_paneStack) return; 3089 if (!m_paneStack) return;
3040 3090
3041 Pane *currentPane = m_paneStack->getCurrentPane(); 3091 Pane *currentPane = m_paneStack->getCurrentPane();
3042 if (!currentPane) return; 3092 if (!currentPane) return;
3043 3093
3094 int count = currentPane->getLayerCount();
3095 if (count == 0) return;
3096
3044 Layer *currentLayer = currentPane->getSelectedLayer(); 3097 Layer *currentLayer = currentPane->getSelectedLayer();
3045 if (!currentLayer) return; 3098
3046 3099 if (!currentLayer) {
3047 for (int i = 0; i < currentPane->getLayerCount(); ++i) { 3100 // The pane itself is current
3048 if (currentPane->getLayer(i) == currentLayer) { 3101 m_paneStack->setCurrentLayer
3049 if (i == currentPane->getLayerCount()-1) return; 3102 (currentPane, currentPane->getFixedOrderLayer(0));
3050 m_paneStack->setCurrentLayer(currentPane, 3103 } else {
3051 currentPane->getLayer(i+1)); 3104 for (int i = 0; i < count; ++i) {
3052 updateMenuStates(); 3105 if (currentPane->getFixedOrderLayer(i) == currentLayer) {
3053 return; 3106 if (i == currentPane->getLayerCount()-1) {
3054 } 3107 m_paneStack->setCurrentLayer
3055 } 3108 (currentPane, 0); // pane
3109 } else {
3110 m_paneStack->setCurrentLayer
3111 (currentPane, currentPane->getFixedOrderLayer(i+1));
3112 }
3113 break;
3114 }
3115 }
3116 }
3117
3118 updateMenuStates();
3056 } 3119 }
3057 3120
3058 void 3121 void
3059 MainWindowBase::playbackFrameChanged(int frame) 3122 MainWindowBase::playbackFrameChanged(int frame)
3060 { 3123 {