comparison main/MainWindow.cpp @ 66:cf27fc7feb7a

* Add Pane menu entries for generating spectrogram etc from non-main models * Some restructuring of MainWindow menu setup code
author Chris Cannam
date Fri, 20 Oct 2006 16:47:13 +0000
parents 77c083741589
children 0229bec2d2dc
comparison
equal deleted inserted replaced
65:77c083741589 66:cf27fc7feb7a
175 m_playSpeed->setValue(100); 175 m_playSpeed->setValue(100);
176 m_playSpeed->setFixedWidth(24); 176 m_playSpeed->setFixedWidth(24);
177 m_playSpeed->setFixedHeight(24); 177 m_playSpeed->setFixedHeight(24);
178 m_playSpeed->setNotchesVisible(true); 178 m_playSpeed->setNotchesVisible(true);
179 m_playSpeed->setPageStep(10); 179 m_playSpeed->setPageStep(10);
180 //!!! m_playSpeed->setToolTip(tr("Playback speed: +0%"));
181 m_playSpeed->setObjectName(tr("Playback Speedup")); 180 m_playSpeed->setObjectName(tr("Playback Speedup"));
182 m_playSpeed->setDefaultValue(100); 181 m_playSpeed->setDefaultValue(100);
183 m_playSpeed->setRangeMapper(new PlaySpeedRangeMapper(0, 200)); 182 m_playSpeed->setRangeMapper(new PlaySpeedRangeMapper(0, 200));
184 m_playSpeed->setShowToolTip(true); 183 m_playSpeed->setShowToolTip(true);
185 connect(m_playSpeed, SIGNAL(valueChanged(int)), 184 connect(m_playSpeed, SIGNAL(valueChanged(int)),
248 } 247 }
249 248
250 void 249 void
251 MainWindow::setupMenus() 250 MainWindow::setupMenus()
252 { 251 {
253 QAction *action = 0;
254 QMenu *menu = 0;
255 QToolBar *toolbar = 0;
256
257 if (!m_mainMenusCreated) { 252 if (!m_mainMenusCreated) {
258 m_rightButtonMenu = new QMenu(); 253 m_rightButtonMenu = new QMenu();
259 } 254 }
260 255
261 if (m_rightButtonLayerMenu) { 256 if (m_rightButtonLayerMenu) {
271 m_rightButtonTransformsMenu = m_rightButtonMenu->addMenu(tr("&Transform")); 266 m_rightButtonTransformsMenu = m_rightButtonMenu->addMenu(tr("&Transform"));
272 m_rightButtonMenu->addSeparator(); 267 m_rightButtonMenu->addSeparator();
273 } 268 }
274 269
275 if (!m_mainMenusCreated) { 270 if (!m_mainMenusCreated) {
276
277 CommandHistory::getInstance()->registerMenu(m_rightButtonMenu); 271 CommandHistory::getInstance()->registerMenu(m_rightButtonMenu);
278 m_rightButtonMenu->addSeparator(); 272 m_rightButtonMenu->addSeparator();
279 273 }
280 menu = menuBar()->addMenu(tr("&File")); 274
281 toolbar = addToolBar(tr("File Toolbar")); 275 setupFileMenu();
282 276 setupEditMenu();
283 QIcon icon(":icons/filenew.png"); 277 setupViewMenu();
284 icon.addFile(":icons/filenew-22.png"); 278 setupPaneAndLayerMenus();
285 action = new QAction(icon, tr("&New Session"), this); 279 setupTransformsMenu();
286 action->setShortcut(tr("Ctrl+N")); 280 setupHelpMenu();
287 action->setStatusTip(tr("Clear the current Sonic Visualiser session and start a new one")); 281
288 connect(action, SIGNAL(triggered()), this, SLOT(newSession())); 282 m_mainMenusCreated = true;
289 menu->addAction(action); 283 }
290 toolbar->addAction(action); 284
285 void
286 MainWindow::setupFileMenu()
287 {
288 if (m_mainMenusCreated) return;
289
290 QMenu *menu = menuBar()->addMenu(tr("&File"));
291 QToolBar *toolbar = addToolBar(tr("File Toolbar"));
292
293 QIcon icon(":icons/filenew.png");
294 icon.addFile(":icons/filenew-22.png");
295 QAction *action = new QAction(icon, tr("&New Session"), this);
296 action->setShortcut(tr("Ctrl+N"));
297 action->setStatusTip(tr("Clear the current Sonic Visualiser session and start a new one"));
298 connect(action, SIGNAL(triggered()), this, SLOT(newSession()));
299 menu->addAction(action);
300 toolbar->addAction(action);
291 301
292 icon = QIcon(":icons/fileopen.png"); 302 icon = QIcon(":icons/fileopen.png");
293 icon.addFile(":icons/fileopen-22.png"); 303 icon.addFile(":icons/fileopen-22.png");
294 304
295 action = new QAction(icon, tr("&Open Session..."), this); 305 action = new QAction(icon, tr("&Open Session..."), this);
296 action->setShortcut(tr("Ctrl+O")); 306 action->setShortcut(tr("Ctrl+O"));
297 action->setStatusTip(tr("Open a previously saved Sonic Visualiser session file")); 307 action->setStatusTip(tr("Open a previously saved Sonic Visualiser session file"));
298 connect(action, SIGNAL(triggered()), this, SLOT(openSession())); 308 connect(action, SIGNAL(triggered()), this, SLOT(openSession()));
299 menu->addAction(action); 309 menu->addAction(action);
300 310
301 action = new QAction(icon, tr("&Open..."), this); 311 action = new QAction(icon, tr("&Open..."), this);
302 action->setStatusTip(tr("Open a session file, audio file, or layer")); 312 action->setStatusTip(tr("Open a session file, audio file, or layer"));
303 connect(action, SIGNAL(triggered()), this, SLOT(openSomething())); 313 connect(action, SIGNAL(triggered()), this, SLOT(openSomething()));
304 toolbar->addAction(action); 314 toolbar->addAction(action);
305 315
306 icon = QIcon(":icons/filesave.png"); 316 icon = QIcon(":icons/filesave.png");
307 icon.addFile(":icons/filesave-22.png"); 317 icon.addFile(":icons/filesave-22.png");
308 action = new QAction(icon, tr("&Save Session"), this); 318 action = new QAction(icon, tr("&Save Session"), this);
309 action->setShortcut(tr("Ctrl+S")); 319 action->setShortcut(tr("Ctrl+S"));
310 action->setStatusTip(tr("Save the current session into a Sonic Visualiser session file")); 320 action->setStatusTip(tr("Save the current session into a Sonic Visualiser session file"));
311 connect(action, SIGNAL(triggered()), this, SLOT(saveSession())); 321 connect(action, SIGNAL(triggered()), this, SLOT(saveSession()));
312 connect(this, SIGNAL(canSave(bool)), action, SLOT(setEnabled(bool))); 322 connect(this, SIGNAL(canSave(bool)), action, SLOT(setEnabled(bool)));
313 menu->addAction(action); 323 menu->addAction(action);
314 toolbar->addAction(action); 324 toolbar->addAction(action);
315 325
316 icon = QIcon(":icons/filesaveas.png"); 326 icon = QIcon(":icons/filesaveas.png");
317 icon.addFile(":icons/filesaveas-22.png"); 327 icon.addFile(":icons/filesaveas-22.png");
318 action = new QAction(icon, tr("Save Session &As..."), this); 328 action = new QAction(icon, tr("Save Session &As..."), this);
319 action->setStatusTip(tr("Save the current session into a new Sonic Visualiser session file")); 329 action->setStatusTip(tr("Save the current session into a new Sonic Visualiser session file"));
320 connect(action, SIGNAL(triggered()), this, SLOT(saveSessionAs())); 330 connect(action, SIGNAL(triggered()), this, SLOT(saveSessionAs()));
321 menu->addAction(action); 331 menu->addAction(action);
322 toolbar->addAction(action); 332 toolbar->addAction(action);
323 333
324 menu->addSeparator(); 334 menu->addSeparator();
325 335
326 action = new QAction(tr("&Import Audio File..."), this); 336 action = new QAction(tr("&Import Audio File..."), this);
327 action->setShortcut(tr("Ctrl+I")); 337 action->setShortcut(tr("Ctrl+I"));
328 action->setStatusTip(tr("Import an existing audio file")); 338 action->setStatusTip(tr("Import an existing audio file"));
329 connect(action, SIGNAL(triggered()), this, SLOT(importAudio())); 339 connect(action, SIGNAL(triggered()), this, SLOT(importAudio()));
330 menu->addAction(action); 340 menu->addAction(action);
331 341
332 action = new QAction(tr("Import Secondary Audio File..."), this); 342 action = new QAction(tr("Import Secondary Audio File..."), this);
333 action->setShortcut(tr("Ctrl+Shift+I")); 343 action->setShortcut(tr("Ctrl+Shift+I"));
334 action->setStatusTip(tr("Import an extra audio file as a separate layer")); 344 action->setStatusTip(tr("Import an extra audio file as a separate layer"));
335 connect(action, SIGNAL(triggered()), this, SLOT(importMoreAudio())); 345 connect(action, SIGNAL(triggered()), this, SLOT(importMoreAudio()));
336 connect(this, SIGNAL(canImportMoreAudio(bool)), action, SLOT(setEnabled(bool))); 346 connect(this, SIGNAL(canImportMoreAudio(bool)), action, SLOT(setEnabled(bool)));
337 menu->addAction(action); 347 menu->addAction(action);
338 348
339 action = new QAction(tr("&Export Audio File..."), this); 349 action = new QAction(tr("&Export Audio File..."), this);
340 action->setStatusTip(tr("Export selection as an audio file")); 350 action->setStatusTip(tr("Export selection as an audio file"));
341 connect(action, SIGNAL(triggered()), this, SLOT(exportAudio())); 351 connect(action, SIGNAL(triggered()), this, SLOT(exportAudio()));
342 connect(this, SIGNAL(canExportAudio(bool)), action, SLOT(setEnabled(bool))); 352 connect(this, SIGNAL(canExportAudio(bool)), action, SLOT(setEnabled(bool)));
343 menu->addAction(action); 353 menu->addAction(action);
344 354
345 menu->addSeparator(); 355 menu->addSeparator();
346 356
347 action = new QAction(tr("Import Annotation &Layer..."), this); 357 action = new QAction(tr("Import Annotation &Layer..."), this);
348 action->setShortcut(tr("Ctrl+L")); 358 action->setShortcut(tr("Ctrl+L"));
349 action->setStatusTip(tr("Import layer data from an existing file")); 359 action->setStatusTip(tr("Import layer data from an existing file"));
350 connect(action, SIGNAL(triggered()), this, SLOT(importLayer())); 360 connect(action, SIGNAL(triggered()), this, SLOT(importLayer()));
351 connect(this, SIGNAL(canImportLayer(bool)), action, SLOT(setEnabled(bool))); 361 connect(this, SIGNAL(canImportLayer(bool)), action, SLOT(setEnabled(bool)));
352 menu->addAction(action); 362 menu->addAction(action);
353 363
354 action = new QAction(tr("Export Annotation Layer..."), this); 364 action = new QAction(tr("Export Annotation Layer..."), this);
355 action->setStatusTip(tr("Export layer data to a file")); 365 action->setStatusTip(tr("Export layer data to a file"));
356 connect(action, SIGNAL(triggered()), this, SLOT(exportLayer())); 366 connect(action, SIGNAL(triggered()), this, SLOT(exportLayer()));
357 connect(this, SIGNAL(canExportLayer(bool)), action, SLOT(setEnabled(bool))); 367 connect(this, SIGNAL(canExportLayer(bool)), action, SLOT(setEnabled(bool)));
358 menu->addAction(action); 368 menu->addAction(action);
359 369
360 menu->addSeparator(); 370 menu->addSeparator();
361 m_recentFilesMenu = menu->addMenu(tr("&Recent Files")); 371 m_recentFilesMenu = menu->addMenu(tr("&Recent Files"));
362 setupRecentFilesMenu(); 372 setupRecentFilesMenu();
363 connect(&m_recentFiles, SIGNAL(recentChanged()), 373 connect(&m_recentFiles, SIGNAL(recentChanged()),
364 this, SLOT(setupRecentFilesMenu())); 374 this, SLOT(setupRecentFilesMenu()));
365 375
366 menu->addSeparator(); 376 menu->addSeparator();
367 action = new QAction(tr("&Preferences..."), this); 377 action = new QAction(tr("&Preferences..."), this);
368 action->setStatusTip(tr("Adjust the application preferences")); 378 action->setStatusTip(tr("Adjust the application preferences"));
369 connect(action, SIGNAL(triggered()), this, SLOT(preferences())); 379 connect(action, SIGNAL(triggered()), this, SLOT(preferences()));
370 menu->addAction(action); 380 menu->addAction(action);
371 381
372 /*!!! 382 /*!!!
373 menu->addSeparator(); 383 menu->addSeparator();
374 384
375 action = new QAction(tr("Play / Pause"), this); 385 action = new QAction(tr("Play / Pause"), this);
376 action->setShortcut(tr("Space")); 386 action->setShortcut(tr("Space"));
377 action->setStatusTip(tr("Start or stop playback from the current position")); 387 action->setStatusTip(tr("Start or stop playback from the current position"));
378 connect(action, SIGNAL(triggered()), this, SLOT(play())); 388 connect(action, SIGNAL(triggered()), this, SLOT(play()));
379 menu->addAction(action); 389 menu->addAction(action);
380 */ 390 */
381 391
382 menu->addSeparator(); 392 menu->addSeparator();
383 action = new QAction(QIcon(":/icons/exit.png"), 393 action = new QAction(QIcon(":/icons/exit.png"),
384 tr("&Quit"), this); 394 tr("&Quit"), this);
385 action->setShortcut(tr("Ctrl+Q")); 395 action->setShortcut(tr("Ctrl+Q"));
386 connect(action, SIGNAL(triggered()), this, SLOT(close())); 396 connect(action, SIGNAL(triggered()), this, SLOT(close()));
387 menu->addAction(action); 397 menu->addAction(action);
388 398 }
389 menu = menuBar()->addMenu(tr("&Edit")); 399
390 CommandHistory::getInstance()->registerMenu(menu); 400 void
391 401 MainWindow::setupEditMenu()
392 menu->addSeparator(); 402 {
393 403 if (m_mainMenusCreated) return;
394 action = new QAction(QIcon(":/icons/editcut.png"), 404
395 tr("Cu&t"), this); 405 QMenu *menu = menuBar()->addMenu(tr("&Edit"));
396 action->setShortcut(tr("Ctrl+X")); 406 CommandHistory::getInstance()->registerMenu(menu);
397 connect(action, SIGNAL(triggered()), this, SLOT(cut())); 407
398 connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool))); 408 menu->addSeparator();
399 menu->addAction(action); 409
400 m_rightButtonMenu->addAction(action); 410 QAction *action = new QAction(QIcon(":/icons/editcut.png"),
401 411 tr("Cu&t"), this);
402 action = new QAction(QIcon(":/icons/editcopy.png"), 412 action->setShortcut(tr("Ctrl+X"));
403 tr("&Copy"), this); 413 connect(action, SIGNAL(triggered()), this, SLOT(cut()));
404 action->setShortcut(tr("Ctrl+C")); 414 connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool)));
405 connect(action, SIGNAL(triggered()), this, SLOT(copy())); 415 menu->addAction(action);
406 connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool))); 416 m_rightButtonMenu->addAction(action);
407 menu->addAction(action); 417
408 m_rightButtonMenu->addAction(action); 418 action = new QAction(QIcon(":/icons/editcopy.png"),
409 419 tr("&Copy"), this);
410 action = new QAction(QIcon(":/icons/editpaste.png"), 420 action->setShortcut(tr("Ctrl+C"));
411 tr("&Paste"), this); 421 connect(action, SIGNAL(triggered()), this, SLOT(copy()));
412 action->setShortcut(tr("Ctrl+V")); 422 connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool)));
413 connect(action, SIGNAL(triggered()), this, SLOT(paste())); 423 menu->addAction(action);
414 connect(this, SIGNAL(canPaste(bool)), action, SLOT(setEnabled(bool))); 424 m_rightButtonMenu->addAction(action);
415 menu->addAction(action); 425
416 m_rightButtonMenu->addAction(action); 426 action = new QAction(QIcon(":/icons/editpaste.png"),
417 427 tr("&Paste"), this);
418 action = new QAction(tr("&Delete Selected Items"), this); 428 action->setShortcut(tr("Ctrl+V"));
419 action->setShortcut(tr("Del")); 429 connect(action, SIGNAL(triggered()), this, SLOT(paste()));
420 connect(action, SIGNAL(triggered()), this, SLOT(deleteSelected())); 430 connect(this, SIGNAL(canPaste(bool)), action, SLOT(setEnabled(bool)));
421 connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool))); 431 menu->addAction(action);
422 menu->addAction(action); 432 m_rightButtonMenu->addAction(action);
423 m_rightButtonMenu->addAction(action); 433
424 434 action = new QAction(tr("&Delete Selected Items"), this);
425 menu->addSeparator(); 435 action->setShortcut(tr("Del"));
426 m_rightButtonMenu->addSeparator(); 436 connect(action, SIGNAL(triggered()), this, SLOT(deleteSelected()));
437 connect(this, SIGNAL(canEditSelection(bool)), action, SLOT(setEnabled(bool)));
438 menu->addAction(action);
439 m_rightButtonMenu->addAction(action);
440
441 menu->addSeparator();
442 m_rightButtonMenu->addSeparator();
427 443
428 action = new QAction(tr("Select &All"), this); 444 action = new QAction(tr("Select &All"), this);
429 action->setShortcut(tr("Ctrl+A")); 445 action->setShortcut(tr("Ctrl+A"));
430 connect(action, SIGNAL(triggered()), this, SLOT(selectAll())); 446 connect(action, SIGNAL(triggered()), this, SLOT(selectAll()));
431 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); 447 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool)));
432 menu->addAction(action); 448 menu->addAction(action);
433 m_rightButtonMenu->addAction(action); 449 m_rightButtonMenu->addAction(action);
434 450
435 action = new QAction(tr("Select &Visible Range"), this); 451 action = new QAction(tr("Select &Visible Range"), this);
436 action->setShortcut(tr("Ctrl+Shift+A")); 452 action->setShortcut(tr("Ctrl+Shift+A"));
437 connect(action, SIGNAL(triggered()), this, SLOT(selectVisible())); 453 connect(action, SIGNAL(triggered()), this, SLOT(selectVisible()));
438 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); 454 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool)));
439 menu->addAction(action); 455 menu->addAction(action);
440 456
441 action = new QAction(tr("Select to &Start"), this); 457 action = new QAction(tr("Select to &Start"), this);
442 action->setShortcut(tr("Shift+Left")); 458 action->setShortcut(tr("Shift+Left"));
443 connect(action, SIGNAL(triggered()), this, SLOT(selectToStart())); 459 connect(action, SIGNAL(triggered()), this, SLOT(selectToStart()));
444 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); 460 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool)));
445 menu->addAction(action); 461 menu->addAction(action);
446 462
447 action = new QAction(tr("Select to &End"), this); 463 action = new QAction(tr("Select to &End"), this);
448 action->setShortcut(tr("Shift+Right")); 464 action->setShortcut(tr("Shift+Right"));
449 connect(action, SIGNAL(triggered()), this, SLOT(selectToEnd())); 465 connect(action, SIGNAL(triggered()), this, SLOT(selectToEnd()));
450 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool))); 466 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool)));
451 menu->addAction(action); 467 menu->addAction(action);
452 468
453 action = new QAction(tr("C&lear Selection"), this); 469 action = new QAction(tr("C&lear Selection"), this);
454 action->setShortcut(tr("Esc")); 470 action->setShortcut(tr("Esc"));
455 connect(action, SIGNAL(triggered()), this, SLOT(clearSelection())); 471 connect(action, SIGNAL(triggered()), this, SLOT(clearSelection()));
456 connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool))); 472 connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
457 menu->addAction(action); 473 menu->addAction(action);
458 m_rightButtonMenu->addAction(action); 474 m_rightButtonMenu->addAction(action);
459 475
460 menu->addSeparator(); 476 menu->addSeparator();
461 477
462 action = new QAction(tr("&Insert Instant at Playback Position"), this); 478 action = new QAction(tr("&Insert Instant at Playback Position"), this);
463 action->setShortcut(tr("Enter")); 479 action->setShortcut(tr("Enter"));
464 connect(action, SIGNAL(triggered()), this, SLOT(insertInstant())); 480 connect(action, SIGNAL(triggered()), this, SLOT(insertInstant()));
465 connect(this, SIGNAL(canInsertInstant(bool)), action, SLOT(setEnabled(bool))); 481 connect(this, SIGNAL(canInsertInstant(bool)), action, SLOT(setEnabled(bool)));
466 menu->addAction(action); 482 menu->addAction(action);
467 483
468 // Laptop shortcut (no keypad Enter key) 484 // Laptop shortcut (no keypad Enter key)
469 connect(new QShortcut(tr(";"), this), SIGNAL(activated()), 485 connect(new QShortcut(tr(";"), this), SIGNAL(activated()),
470 this, SLOT(insertInstant())); 486 this, SLOT(insertInstant()));
471 487 }
472 menu = menuBar()->addMenu(tr("&View")); 488
473 489 void
474 QActionGroup *overlayGroup = new QActionGroup(this); 490 MainWindow::setupViewMenu()
491 {
492 if (m_mainMenusCreated) return;
493
494 QMenu *menu = menuBar()->addMenu(tr("&View"));
495
496 QActionGroup *overlayGroup = new QActionGroup(this);
475 497
476 action = new QAction(tr("&No Text Overlays"), this); 498 QAction *action = new QAction(tr("&No Text Overlays"), this);
477 action->setShortcut(tr("0")); 499 action->setShortcut(tr("0"));
478 action->setStatusTip(tr("Show no texts for frame times, layer names etc")); 500 action->setStatusTip(tr("Show no texts for frame times, layer names etc"));
479 connect(action, SIGNAL(triggered()), this, SLOT(showNoOverlays())); 501 connect(action, SIGNAL(triggered()), this, SLOT(showNoOverlays()));
480 action->setCheckable(true); 502 action->setCheckable(true);
481 action->setChecked(false); 503 action->setChecked(false);
482 overlayGroup->addAction(action); 504 overlayGroup->addAction(action);
483 menu->addAction(action); 505 menu->addAction(action);
484 506
485 action = new QAction(tr("Basic &Text Overlays"), this); 507 action = new QAction(tr("Basic &Text Overlays"), this);
486 action->setShortcut(tr("9")); 508 action->setShortcut(tr("9"));
487 action->setStatusTip(tr("Show texts for frame times etc, but not layer names etc")); 509 action->setStatusTip(tr("Show texts for frame times etc, but not layer names etc"));
488 connect(action, SIGNAL(triggered()), this, SLOT(showBasicOverlays())); 510 connect(action, SIGNAL(triggered()), this, SLOT(showBasicOverlays()));
489 action->setCheckable(true); 511 action->setCheckable(true);
490 action->setChecked(true); 512 action->setChecked(true);
491 overlayGroup->addAction(action); 513 overlayGroup->addAction(action);
492 menu->addAction(action); 514 menu->addAction(action);
493 515
494 action = new QAction(tr("&All Text Overlays"), this); 516 action = new QAction(tr("&All Text Overlays"), this);
495 action->setShortcut(tr("8")); 517 action->setShortcut(tr("8"));
496 action->setStatusTip(tr("Show texts for frame times, layer names etc")); 518 action->setStatusTip(tr("Show texts for frame times, layer names etc"));
497 connect(action, SIGNAL(triggered()), this, SLOT(showAllTextOverlays())); 519 connect(action, SIGNAL(triggered()), this, SLOT(showAllTextOverlays()));
498 action->setCheckable(true); 520 action->setCheckable(true);
499 action->setChecked(false); 521 action->setChecked(false);
500 overlayGroup->addAction(action); 522 overlayGroup->addAction(action);
501 menu->addAction(action); 523 menu->addAction(action);
502 524
503 menu->addSeparator(); 525 menu->addSeparator();
504 526
505 action = new QAction(tr("Scroll &Left"), this); 527 action = new QAction(tr("Scroll &Left"), this);
506 action->setShortcut(tr("Left")); 528 action->setShortcut(tr("Left"));
507 action->setStatusTip(tr("Scroll the current pane to the left")); 529 action->setStatusTip(tr("Scroll the current pane to the left"));
508 connect(action, SIGNAL(triggered()), this, SLOT(scrollLeft())); 530 connect(action, SIGNAL(triggered()), this, SLOT(scrollLeft()));
509 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); 531 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
510 menu->addAction(action); 532 menu->addAction(action);
511 533
512 action = new QAction(tr("Scroll &Right"), this); 534 action = new QAction(tr("Scroll &Right"), this);
513 action->setShortcut(tr("Right")); 535 action->setShortcut(tr("Right"));
514 action->setStatusTip(tr("Scroll the current pane to the right")); 536 action->setStatusTip(tr("Scroll the current pane to the right"));
515 connect(action, SIGNAL(triggered()), this, SLOT(scrollRight())); 537 connect(action, SIGNAL(triggered()), this, SLOT(scrollRight()));
516 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); 538 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
517 menu->addAction(action); 539 menu->addAction(action);
518 540
519 action = new QAction(tr("Jump Left"), this); 541 action = new QAction(tr("Jump Left"), this);
520 action->setShortcut(tr("Ctrl+Left")); 542 action->setShortcut(tr("Ctrl+Left"));
521 action->setStatusTip(tr("Scroll the current pane a big step to the left")); 543 action->setStatusTip(tr("Scroll the current pane a big step to the left"));
522 connect(action, SIGNAL(triggered()), this, SLOT(jumpLeft())); 544 connect(action, SIGNAL(triggered()), this, SLOT(jumpLeft()));
523 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); 545 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
524 menu->addAction(action); 546 menu->addAction(action);
525 547
526 action = new QAction(tr("Jump Right"), this); 548 action = new QAction(tr("Jump Right"), this);
527 action->setShortcut(tr("Ctrl+Right")); 549 action->setShortcut(tr("Ctrl+Right"));
528 action->setStatusTip(tr("Scroll the current pane a big step to the right")); 550 action->setStatusTip(tr("Scroll the current pane a big step to the right"));
529 connect(action, SIGNAL(triggered()), this, SLOT(jumpRight())); 551 connect(action, SIGNAL(triggered()), this, SLOT(jumpRight()));
530 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool))); 552 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
531 menu->addAction(action); 553 menu->addAction(action);
532 554
533 menu->addSeparator(); 555 menu->addSeparator();
534 556
535 action = new QAction(QIcon(":/icons/zoom-in.png"), 557 action = new QAction(QIcon(":/icons/zoom-in.png"),
536 tr("Zoom &In"), this); 558 tr("Zoom &In"), this);
537 action->setShortcut(tr("Up")); 559 action->setShortcut(tr("Up"));
538 action->setStatusTip(tr("Increase the zoom level")); 560 action->setStatusTip(tr("Increase the zoom level"));
539 connect(action, SIGNAL(triggered()), this, SLOT(zoomIn())); 561 connect(action, SIGNAL(triggered()), this, SLOT(zoomIn()));
540 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); 562 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
541 menu->addAction(action); 563 menu->addAction(action);
542 564
543 action = new QAction(QIcon(":/icons/zoom-out.png"), 565 action = new QAction(QIcon(":/icons/zoom-out.png"),
544 tr("Zoom &Out"), this); 566 tr("Zoom &Out"), this);
545 action->setShortcut(tr("Down")); 567 action->setShortcut(tr("Down"));
546 action->setStatusTip(tr("Decrease the zoom level")); 568 action->setStatusTip(tr("Decrease the zoom level"));
547 connect(action, SIGNAL(triggered()), this, SLOT(zoomOut())); 569 connect(action, SIGNAL(triggered()), this, SLOT(zoomOut()));
548 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); 570 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
549 menu->addAction(action); 571 menu->addAction(action);
550 572
551 action = new QAction(tr("Restore &Default Zoom"), this); 573 action = new QAction(tr("Restore &Default Zoom"), this);
552 connect(action, SIGNAL(triggered()), this, SLOT(zoomDefault())); 574 connect(action, SIGNAL(triggered()), this, SLOT(zoomDefault()));
553 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); 575 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
554 menu->addAction(action); 576 menu->addAction(action);
555 577
556 action = new QAction(tr("Zoom to &Fit"), this); 578 action = new QAction(tr("Zoom to &Fit"), this);
557 action->setStatusTip(tr("Zoom to show the whole file")); 579 action->setStatusTip(tr("Zoom to show the whole file"));
558 connect(action, SIGNAL(triggered()), this, SLOT(zoomToFit())); 580 connect(action, SIGNAL(triggered()), this, SLOT(zoomToFit()));
559 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool))); 581 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
560 menu->addAction(action); 582 menu->addAction(action);
561 583
562 action = new QAction(tr("Show &Zoom Wheels"), this); 584 action = new QAction(tr("Show &Zoom Wheels"), this);
563 action->setShortcut(tr("Z")); 585 action->setShortcut(tr("Z"));
564 action->setStatusTip(tr("Show thumbwheels for zooming horizontally and vertically")); 586 action->setStatusTip(tr("Show thumbwheels for zooming horizontally and vertically"));
565 connect(action, SIGNAL(triggered()), this, SLOT(toggleZoomWheels())); 587 connect(action, SIGNAL(triggered()), this, SLOT(toggleZoomWheels()));
566 action->setCheckable(true); 588 action->setCheckable(true);
567 action->setChecked(m_viewManager->getZoomWheelsEnabled()); 589 action->setChecked(m_viewManager->getZoomWheelsEnabled());
568 menu->addAction(action); 590 menu->addAction(action);
569 591
570 /*!!! This one doesn't work properly yet 592 /*!!! This one doesn't work properly yet
571 */ 593 */
572 menu->addSeparator(); 594 menu->addSeparator();
573 595
574 action = new QAction(tr("Show &Layer Hierarchy"), this); 596 action = new QAction(tr("Show &Layer Hierarchy"), this);
575 action->setShortcut(tr("Alt+L")); 597 action->setShortcut(tr("Alt+L"));
576 connect(action, SIGNAL(triggered()), this, SLOT(showLayerTree())); 598 connect(action, SIGNAL(triggered()), this, SLOT(showLayerTree()));
577 menu->addAction(action); 599 menu->addAction(action);
578 /* */ 600 /* */
579 } 601 }
580 602
603 void
604 MainWindow::setupPaneAndLayerMenus()
605 {
581 if (m_paneMenu) { 606 if (m_paneMenu) {
582 m_paneActions.clear(); 607 m_paneActions.clear();
583 m_paneMenu->clear(); 608 m_paneMenu->clear();
584 } else { 609 } else {
585 m_paneMenu = menuBar()->addMenu(tr("&Pane")); 610 m_paneMenu = menuBar()->addMenu(tr("&Pane"));
590 m_layerMenu->clear(); 615 m_layerMenu->clear();
591 } else { 616 } else {
592 m_layerMenu = menuBar()->addMenu(tr("&Layer")); 617 m_layerMenu = menuBar()->addMenu(tr("&Layer"));
593 } 618 }
594 619
620 QMenu *menu = m_paneMenu;
621
622 QAction *action = new QAction(QIcon(":/icons/pane.png"), tr("Add &New Pane"), this);
623 action->setShortcut(tr("Alt+N"));
624 action->setStatusTip(tr("Add a new pane containing only a time ruler"));
625 connect(action, SIGNAL(triggered()), this, SLOT(addPane()));
626 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool)));
627 m_paneActions[action] = PaneConfiguration(LayerFactory::TimeRuler);
628 menu->addAction(action);
629
630 menu->addSeparator();
631
632 menu = m_layerMenu;
633
634 // menu->addSeparator();
635
636 LayerFactory::LayerTypeSet emptyLayerTypes =
637 LayerFactory::getInstance()->getValidEmptyLayerTypes();
638
639 for (LayerFactory::LayerTypeSet::iterator i = emptyLayerTypes.begin();
640 i != emptyLayerTypes.end(); ++i) {
641
642 QIcon icon;
643 QString mainText, tipText, channelText;
644 LayerFactory::LayerType type = *i;
645 QString name = LayerFactory::getInstance()->getLayerPresentationName(type);
646
647 icon = QIcon(QString(":/icons/%1.png")
648 .arg(LayerFactory::getInstance()->getLayerIconName(type)));
649
650 mainText = tr("Add New %1 Layer").arg(name);
651 tipText = tr("Add a new empty layer of type %1").arg(name);
652
653 action = new QAction(icon, mainText, this);
654 action->setStatusTip(tipText);
655
656 if (type == LayerFactory::Text) {
657 action->setShortcut(tr("Alt+T"));
658 }
659
660 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
661 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
662 m_layerActions[action] = type;
663 menu->addAction(action);
664 m_rightButtonLayerMenu->addAction(action);
665 }
666
667 m_rightButtonLayerMenu->addSeparator();
668 menu->addSeparator();
669
670 LayerFactory::LayerType backgroundTypes[] = {
671 LayerFactory::Waveform,
672 LayerFactory::Spectrogram,
673 LayerFactory::MelodicRangeSpectrogram,
674 LayerFactory::PeakFrequencySpectrogram,
675 LayerFactory::Spectrum
676 };
677
678 std::vector<Model *> models;
679 if (m_document) models = m_document->getTransformInputModels(); //!!! not well named for this!
680 bool plural = (models.size() > 1);
681 if (models.empty()) {
682 if (m_document) {
683 models.push_back(m_document->getMainModel()); // probably 0
684 } else {
685 models.push_back(0);
686 }
687 }
688
689 for (unsigned int i = 0;
690 i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) {
691
692 for (int menuType = 0; menuType <= 1; ++menuType) { // pane, layer
693
694 if (menuType == 0) menu = m_paneMenu;
695 else menu = m_layerMenu;
696
697 QMenu *submenu = 0;
698
699 QIcon icon;
700 QString mainText, shortcutText, tipText, channelText;
701 LayerFactory::LayerType type = backgroundTypes[i];
702 bool mono = true;
703
704 switch (type) {
705
706 case LayerFactory::Waveform:
707 icon = QIcon(":/icons/waveform.png");
708 mainText = tr("Add &Waveform");
709 if (menuType == 0) {
710 shortcutText = tr("Alt+W");
711 tipText = tr("Add a new pane showing a waveform view");
712 } else {
713 tipText = tr("Add a new layer showing a waveform view");
714 }
715 mono = false;
716 break;
717
718 case LayerFactory::Spectrogram:
719 mainText = tr("Add &Spectrogram");
720 if (menuType == 0) {
721 shortcutText = tr("Alt+S");
722 tipText = tr("Add a new pane showing a dB spectrogram");
723 } else {
724 tipText = tr("Add a new layer showing a dB spectrogram");
725 }
726 break;
727
728 case LayerFactory::MelodicRangeSpectrogram:
729 mainText = tr("Add &Melodic Range Spectrogram");
730 if (menuType == 0) {
731 shortcutText = tr("Alt+M");
732 tipText = tr("Add a new pane showing a spectrogram set up for a pitch overview");
733 } else {
734 tipText = tr("Add a new layer showing a spectrogram set up for a pitch overview");
735 }
736 break;
737
738 case LayerFactory::PeakFrequencySpectrogram:
739 mainText = tr("Add &Peak Frequency Spectrogram");
740 if (menuType == 0) {
741 shortcutText = tr("Alt+P");
742 tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies");
743 } else {
744 tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies");
745 }
746 break;
747
748 case LayerFactory::Spectrum:
749 mainText = tr("Add Spectr&um");
750 if (menuType == 0) {
751 shortcutText = tr("Alt+U");
752 tipText = tr("Add a new pane showing a frequency spectrum");
753 } else {
754 tipText = tr("Add a new layer showing a frequency spectrum");
755 }
756 break;
757
758 default: break;
759 }
760
761 std::vector<Model *> candidateModels;
762 if (menuType == 0) {
763 candidateModels = models;
764 } else {
765 candidateModels.push_back(0);
766 }
767
768 for (std::vector<Model *>::iterator mi =
769 candidateModels.begin();
770 mi != candidateModels.end(); ++mi) {
771
772 Model *model = *mi;
773
774 int channels = 0;
775 if (model) {
776 DenseTimeValueModel *dtvm =
777 dynamic_cast<DenseTimeValueModel *>(model);
778 if (dtvm) channels = dtvm->getChannelCount();
779 }
780 if (channels < 1 && getMainModel()) {
781 channels = getMainModel()->getChannelCount();
782 }
783 if (channels < 1) channels = 1;
784
785 for (int c = 0; c <= channels; ++c) {
786
787 if (c == 1 && channels == 1) continue;
788 bool isDefault = (c == 0);
789 bool isOnly = (isDefault && (channels == 1));
790
791 if (menuType == 1) {
792 if (isDefault) isOnly = true;
793 else continue;
794 }
795
796 if (isOnly && (!plural || menuType == 1)) {
797
798 action = new QAction(icon, mainText, this);
799 action->setShortcut(shortcutText);
800 action->setStatusTip(tipText);
801 if (menuType == 0) {
802 connect(action, SIGNAL(triggered()),
803 this, SLOT(addPane()));
804 connect(this, SIGNAL(canAddPane(bool)),
805 action, SLOT(setEnabled(bool)));
806 m_paneActions[action] = PaneConfiguration(type);
807 } else {
808 connect(action, SIGNAL(triggered()),
809 this, SLOT(addLayer()));
810 connect(this, SIGNAL(canAddLayer(bool)),
811 action, SLOT(setEnabled(bool)));
812 m_layerActions[action] = type;
813 }
814 menu->addAction(action);
815
816 } else {
817
818 if (!submenu) {
819 submenu = menu->addMenu(mainText);
820 }
821
822 QString actionText;
823 if (c == 0) {
824 if (mono) {
825 actionText = tr("&All Channels Mixed");
826 } else {
827 actionText = tr("&All Channels");
828 }
829 } else {
830 actionText = tr("Channel &%1").arg(c);
831 }
832
833 if (model) {
834 actionText = tr("%1: %2")
835 .arg(model->objectName())
836 .arg(actionText);
837 }
838
839 action = new QAction(icon, actionText, this);
840 if (isDefault) action->setShortcut(shortcutText);
841 action->setStatusTip(tipText);
842
843 if (menuType == 0) {
844 connect(action, SIGNAL(triggered()),
845 this, SLOT(addPane()));
846 connect(this, SIGNAL(canAddPane(bool)),
847 action, SLOT(setEnabled(bool)));
848 m_paneActions[action] =
849 PaneConfiguration(type, model, c - 1);
850 } else {
851 connect(action, SIGNAL(triggered()),
852 this, SLOT(addLayer()));
853 connect(this, SIGNAL(canAddLayer(bool)),
854 action, SLOT(setEnabled(bool)));
855 m_layerActions[action] = type;
856 }
857
858 submenu->addAction(action);
859 }
860 }
861 }
862 }
863 }
864
865 menu = m_paneMenu;
866
867 menu->addSeparator();
868
869 action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Pane"), this);
870 action->setShortcut(tr("Alt+D"));
871 action->setStatusTip(tr("Delete the currently selected pane"));
872 connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentPane()));
873 connect(this, SIGNAL(canDeleteCurrentPane(bool)), action, SLOT(setEnabled(bool)));
874 menu->addAction(action);
875
876 menu = m_layerMenu;
877
878 action = new QAction(QIcon(":/icons/timeruler.png"), tr("Add &Time Ruler"), this);
879 action->setStatusTip(tr("Add a new layer showing a time ruler"));
880 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
881 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
882 m_layerActions[action] = LayerFactory::TimeRuler;
883 menu->addAction(action);
884
885 menu->addSeparator();
886
887 m_existingLayersMenu = menu->addMenu(tr("Add &Existing Layer"));
888 m_rightButtonLayerMenu->addMenu(m_existingLayersMenu);
889 setupExistingLayersMenu();
890
891 m_rightButtonLayerMenu->addSeparator();
892 menu->addSeparator();
893
894 action = new QAction(tr("&Rename Layer..."), this);
895 action->setShortcut(tr("Alt+R"));
896 action->setStatusTip(tr("Rename the currently active layer"));
897 connect(action, SIGNAL(triggered()), this, SLOT(renameCurrentLayer()));
898 connect(this, SIGNAL(canRenameLayer(bool)), action, SLOT(setEnabled(bool)));
899 menu->addAction(action);
900 m_rightButtonLayerMenu->addAction(action);
901
902 action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Layer"), this);
903 action->setShortcut(tr("Alt+Shift+D"));
904 action->setStatusTip(tr("Delete the currently active layer"));
905 connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentLayer()));
906 connect(this, SIGNAL(canDeleteCurrentLayer(bool)), action, SLOT(setEnabled(bool)));
907 menu->addAction(action);
908 m_rightButtonLayerMenu->addAction(action);
909 }
910
911 void
912 MainWindow::setupTransformsMenu()
913 {
595 if (m_transformsMenu) { 914 if (m_transformsMenu) {
596 m_transformActions.clear(); 915 m_transformActions.clear();
597 m_transformActionsReverse.clear(); 916 m_transformActionsReverse.clear();
598 m_transformsMenu->clear(); 917 m_transformsMenu->clear();
599 } else { 918 } else {
716 maker.replace(QRegExp(tr(" [\\(<].*$")), ""); 1035 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
717 1036
718 QString pluginName = description.section(": ", 0, 0); 1037 QString pluginName = description.section(": ", 0, 0);
719 QString output = description.section(": ", 1); 1038 QString output = description.section(": ", 1);
720 1039
721 action = new QAction(tr("%1...").arg(description), this); 1040 QAction *action = new QAction(tr("%1...").arg(description), this);
722 connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); 1041 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
723 m_transformActions[action] = transforms[i].name; 1042 m_transformActions[action] = transforms[i].name;
724 m_transformActionsReverse[transforms[i].name] = action; 1043 m_transformActionsReverse[transforms[i].name] = action;
725 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); 1044 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
726 1045
775 i != pendingMenus.end(); ++i) { 1094 i != pendingMenus.end(); ++i) {
776 (*i)->entriesAdded(); 1095 (*i)->entriesAdded();
777 } 1096 }
778 1097
779 setupRecentTransformsMenu(); 1098 setupRecentTransformsMenu();
780 1099 }
781 menu = m_paneMenu; 1100
782 1101 void
783 action = new QAction(QIcon(":/icons/pane.png"), tr("Add &New Pane"), this); 1102 MainWindow::setupHelpMenu()
784 action->setShortcut(tr("Alt+N")); 1103 {
785 action->setStatusTip(tr("Add a new pane containing only a time ruler")); 1104 if (m_mainMenusCreated) return;
786 connect(action, SIGNAL(triggered()), this, SLOT(addPane())); 1105
787 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool))); 1106 QMenu *menu = menuBar()->addMenu(tr("&Help"));
788 m_paneActions[action] = PaneConfiguration(LayerFactory::TimeRuler);
789 menu->addAction(action);
790
791 menu->addSeparator();
792
793 menu = m_layerMenu;
794
795 // menu->addSeparator();
796
797 LayerFactory::LayerTypeSet emptyLayerTypes =
798 LayerFactory::getInstance()->getValidEmptyLayerTypes();
799
800 for (LayerFactory::LayerTypeSet::iterator i = emptyLayerTypes.begin();
801 i != emptyLayerTypes.end(); ++i) {
802
803 QIcon icon;
804 QString mainText, tipText, channelText;
805 LayerFactory::LayerType type = *i;
806 QString name = LayerFactory::getInstance()->getLayerPresentationName(type);
807
808 icon = QIcon(QString(":/icons/%1.png")
809 .arg(LayerFactory::getInstance()->getLayerIconName(type)));
810
811 mainText = tr("Add New %1 Layer").arg(name);
812 tipText = tr("Add a new empty layer of type %1").arg(name);
813
814 action = new QAction(icon, mainText, this);
815 action->setStatusTip(tipText);
816
817 if (type == LayerFactory::Text) {
818 action->setShortcut(tr("Alt+T"));
819 }
820
821 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
822 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
823 m_layerActions[action] = type;
824 menu->addAction(action);
825 m_rightButtonLayerMenu->addAction(action);
826 }
827 1107
828 m_rightButtonLayerMenu->addSeparator(); 1108 QAction *action = new QAction(tr("&Help Reference"), this);
829 menu->addSeparator(); 1109 action->setStatusTip(tr("Open the Sonic Visualiser reference manual"));
830 1110 connect(action, SIGNAL(triggered()), this, SLOT(help()));
831 int channels = 1; 1111 menu->addAction(action);
832 if (getMainModel()) channels = getMainModel()->getChannelCount(); 1112
833 1113 action = new QAction(tr("Sonic Visualiser on the &Web"), this);
834 if (channels < 1) channels = 1; 1114 action->setStatusTip(tr("Open the Sonic Visualiser website"));
835 1115 connect(action, SIGNAL(triggered()), this, SLOT(website()));
836 LayerFactory::LayerType backgroundTypes[] = { 1116 menu->addAction(action);
837 LayerFactory::Waveform, 1117
838 LayerFactory::Spectrogram, 1118 action = new QAction(tr("&About Sonic Visualiser"), this);
839 LayerFactory::MelodicRangeSpectrogram, 1119 action->setStatusTip(tr("Show information about Sonic Visualiser"));
840 LayerFactory::PeakFrequencySpectrogram, 1120 connect(action, SIGNAL(triggered()), this, SLOT(about()));
841 LayerFactory::Spectrum 1121 menu->addAction(action);
842 };
843
844 for (unsigned int i = 0;
845 i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) {
846
847 for (int menuType = 0; menuType <= 1; ++menuType) { // pane, layer
848
849 if (menuType == 0) menu = m_paneMenu;
850 else menu = m_layerMenu;
851
852 QMenu *submenu = 0;
853
854 for (int c = 0; c <= channels; ++c) {
855
856 if (c == 1 && channels == 1) continue;
857 bool isDefault = (c == 0);
858 bool isOnly = (isDefault && (channels == 1));
859
860 if (menuType == 1) {
861 if (isDefault) isOnly = true;
862 else continue;
863 }
864
865 QIcon icon;
866 QString mainText, shortcutText, tipText, channelText;
867 LayerFactory::LayerType type = backgroundTypes[i];
868 bool mono = true;
869
870 switch (type) {
871
872 case LayerFactory::Waveform:
873 icon = QIcon(":/icons/waveform.png");
874 mainText = tr("Add &Waveform");
875 if (menuType == 0) {
876 shortcutText = tr("Alt+W");
877 tipText = tr("Add a new pane showing a waveform view");
878 } else {
879 tipText = tr("Add a new layer showing a waveform view");
880 }
881 mono = false;
882 break;
883
884 case LayerFactory::Spectrogram:
885 mainText = tr("Add &Spectrogram");
886 if (menuType == 0) {
887 shortcutText = tr("Alt+S");
888 tipText = tr("Add a new pane showing a dB spectrogram");
889 } else {
890 tipText = tr("Add a new layer showing a dB spectrogram");
891 }
892 break;
893
894 case LayerFactory::MelodicRangeSpectrogram:
895 mainText = tr("Add &Melodic Range Spectrogram");
896 if (menuType == 0) {
897 shortcutText = tr("Alt+M");
898 tipText = tr("Add a new pane showing a spectrogram set up for a pitch overview");
899 } else {
900 tipText = tr("Add a new layer showing a spectrogram set up for a pitch overview");
901 }
902 break;
903
904 case LayerFactory::PeakFrequencySpectrogram:
905 mainText = tr("Add &Peak Frequency Spectrogram");
906 if (menuType == 0) {
907 shortcutText = tr("Alt+P");
908 tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies");
909 } else {
910 tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies");
911 }
912 break;
913
914 case LayerFactory::Spectrum:
915 mainText = tr("Add Spectr&um");
916 if (menuType == 0) {
917 shortcutText = tr("Alt+U");
918 tipText = tr("Add a new pane showing a frequency spectrum");
919 } else {
920 tipText = tr("Add a new layer showing a frequency spectrum");
921 }
922 break;
923
924 default: break;
925 }
926
927 if (isOnly) {
928
929 action = new QAction(icon, mainText, this);
930 action->setShortcut(shortcutText);
931 action->setStatusTip(tipText);
932 if (menuType == 0) {
933 connect(action, SIGNAL(triggered()), this, SLOT(addPane()));
934 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool)));
935 m_paneActions[action] = PaneConfiguration(type);
936 } else {
937 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
938 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
939 m_layerActions[action] = type;
940 }
941 menu->addAction(action);
942
943 } else {
944
945 QString actionText;
946 if (c == 0)
947 if (mono) actionText = tr("&All Channels Mixed");
948 else actionText = tr("&All Channels");
949 else actionText = tr("Channel &%1").arg(c);
950
951 if (!submenu) {
952 submenu = menu->addMenu(mainText);
953 }
954
955 action = new QAction(icon, actionText, this);
956 if (isDefault) action->setShortcut(shortcutText);
957 action->setStatusTip(tipText);
958 if (menuType == 0) {
959 connect(action, SIGNAL(triggered()), this, SLOT(addPane()));
960 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool)));
961 m_paneActions[action] = PaneConfiguration(type, c - 1);
962 } else {
963 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
964 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
965 m_layerActions[action] = type;
966 }
967 submenu->addAction(action);
968 }
969 }
970 }
971 }
972
973 menu = m_paneMenu;
974
975 menu->addSeparator();
976
977 action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Pane"), this);
978 action->setShortcut(tr("Alt+D"));
979 action->setStatusTip(tr("Delete the currently selected pane"));
980 connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentPane()));
981 connect(this, SIGNAL(canDeleteCurrentPane(bool)), action, SLOT(setEnabled(bool)));
982 menu->addAction(action);
983
984 menu = m_layerMenu;
985
986 action = new QAction(QIcon(":/icons/timeruler.png"), tr("Add &Time Ruler"), this);
987 action->setStatusTip(tr("Add a new layer showing a time ruler"));
988 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
989 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
990 m_layerActions[action] = LayerFactory::TimeRuler;
991 menu->addAction(action);
992
993 menu->addSeparator();
994
995 m_existingLayersMenu = menu->addMenu(tr("Add &Existing Layer"));
996 m_rightButtonLayerMenu->addMenu(m_existingLayersMenu);
997 setupExistingLayersMenu();
998
999 m_rightButtonLayerMenu->addSeparator();
1000 menu->addSeparator();
1001
1002 action = new QAction(tr("&Rename Layer..."), this);
1003 action->setShortcut(tr("Alt+R"));
1004 action->setStatusTip(tr("Rename the currently active layer"));
1005 connect(action, SIGNAL(triggered()), this, SLOT(renameCurrentLayer()));
1006 connect(this, SIGNAL(canRenameLayer(bool)), action, SLOT(setEnabled(bool)));
1007 menu->addAction(action);
1008 m_rightButtonLayerMenu->addAction(action);
1009
1010 action = new QAction(QIcon(":/icons/editdelete.png"), tr("&Delete Layer"), this);
1011 action->setShortcut(tr("Alt+Shift+D"));
1012 action->setStatusTip(tr("Delete the currently active layer"));
1013 connect(action, SIGNAL(triggered()), this, SLOT(deleteCurrentLayer()));
1014 connect(this, SIGNAL(canDeleteCurrentLayer(bool)), action, SLOT(setEnabled(bool)));
1015 menu->addAction(action);
1016 m_rightButtonLayerMenu->addAction(action);
1017
1018 if (!m_mainMenusCreated) {
1019
1020 menu = menuBar()->addMenu(tr("&Help"));
1021
1022 action = new QAction(tr("&Help Reference"), this);
1023 action->setStatusTip(tr("Open the Sonic Visualiser reference manual"));
1024 connect(action, SIGNAL(triggered()), this, SLOT(help()));
1025 menu->addAction(action);
1026
1027 action = new QAction(tr("Sonic Visualiser on the &Web"), this);
1028 action->setStatusTip(tr("Open the Sonic Visualiser website"));
1029 connect(action, SIGNAL(triggered()), this, SLOT(website()));
1030 menu->addAction(action);
1031
1032 action = new QAction(tr("&About Sonic Visualiser"), this);
1033 action->setStatusTip(tr("Show information about Sonic Visualiser"));
1034 connect(action, SIGNAL(triggered()), this, SLOT(about()));
1035 menu->addAction(action);
1036 /*
1037 action = new QAction(tr("About &Qt"), this);
1038 action->setStatusTip(tr("Show information about Qt"));
1039 connect(action, SIGNAL(triggered()),
1040 QApplication::getInstance(), SLOT(aboutQt()));
1041 menu->addAction(action);
1042 */
1043 }
1044
1045 m_mainMenusCreated = true;
1046 } 1122 }
1047 1123
1048 void 1124 void
1049 MainWindow::setupRecentFilesMenu() 1125 MainWindow::setupRecentFilesMenu()
1050 { 1126 {
2794 2870
2795 m_document->addLayerToView(pane, m_timeRulerLayer); 2871 m_document->addLayerToView(pane, m_timeRulerLayer);
2796 } 2872 }
2797 2873
2798 Layer *newLayer = m_document->createLayer(i->second.layer); 2874 Layer *newLayer = m_document->createLayer(i->second.layer);
2799 m_document->setModel(newLayer, m_document->getMainModel()); 2875
2876 Model *suggestedModel = i->second.sourceModel;
2877 Model *model = 0;
2878
2879 if (suggestedModel) {
2880
2881 // check its validity
2882 std::vector<Model *> inputModels = m_document->getTransformInputModels();
2883 for (size_t j = 0; j < inputModels.size(); ++j) {
2884 if (inputModels[j] == suggestedModel) {
2885 model = suggestedModel;
2886 break;
2887 }
2888 }
2889
2890 if (!model) {
2891 std::cerr << "WARNING: Model " << (void *)suggestedModel
2892 << " appears in pane action map, but is not reported "
2893 << "by document as a valid transform source" << std::endl;
2894 }
2895 }
2896
2897 if (!model) model = m_document->getMainModel();
2898
2899 m_document->setModel(newLayer, model);
2900
2800 m_document->setChannel(newLayer, i->second.channel); 2901 m_document->setChannel(newLayer, i->second.channel);
2801 m_document->addLayerToView(pane, newLayer); 2902 m_document->addLayerToView(pane, newLayer);
2802 2903
2803 m_paneStack->setCurrentPane(pane); 2904 m_paneStack->setCurrentPane(pane);
2804 2905
2972 // supposed to be configurable, because we need to let the user 3073 // supposed to be configurable, because we need to let the user
2973 // change the execution context (block size etc). 3074 // change the execution context (block size etc).
2974 3075
2975 PluginTransform::ExecutionContext context(channel); 3076 PluginTransform::ExecutionContext context(channel);
2976 3077
2977 std::vector<Model *> candidateInputModels; 3078 std::vector<Model *> candidateInputModels =
2978 candidateInputModels.push_back(m_document->getMainModel()); 3079 m_document->getTransformInputModels();
2979
2980 //!!! rationalise this (via document method for example)
2981 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
2982 Pane *ip = m_paneStack->getPane(i);
2983 if (!ip) continue;
2984 for (int j = 0; j < ip->getLayerCount(); ++j) {
2985 Layer *jl = ip->getLayer(j);
2986 if (jl) {
2987 Model *model = jl->getModel();
2988 DenseTimeValueModel *dtvm = dynamic_cast<DenseTimeValueModel *>
2989 (model);
2990 if (dtvm) {
2991 int k;
2992 for (k = 0; k < candidateInputModels.size(); ++k) {
2993 if (candidateInputModels[k] == dtvm) break;
2994 }
2995 if (k == candidateInputModels.size()) {
2996 candidateInputModels.push_back(dtvm);
2997 }
2998 }
2999 }
3000 }
3001 }
3002 3080
3003 Model *inputModel = factory->getConfigurationForTransform(transform, 3081 Model *inputModel = factory->getConfigurationForTransform(transform,
3004 candidateInputModels, 3082 candidateInputModels,
3005 context, 3083 context,
3006 configurationXml, 3084 configurationXml,
3234 void 3312 void
3235 MainWindow::modelAdded(Model *model) 3313 MainWindow::modelAdded(Model *model)
3236 { 3314 {
3237 // std::cerr << "MainWindow::modelAdded(" << model << ")" << std::endl; 3315 // std::cerr << "MainWindow::modelAdded(" << model << ")" << std::endl;
3238 m_playSource->addModel(model); 3316 m_playSource->addModel(model);
3317 if (dynamic_cast<DenseTimeValueModel *>(model)) {
3318 setupPaneAndLayerMenus();
3319 }
3239 } 3320 }
3240 3321
3241 void 3322 void
3242 MainWindow::mainModelChanged(WaveFileModel *model) 3323 MainWindow::mainModelChanged(WaveFileModel *model)
3243 { 3324 {