musredit 1.0.0
Loading...
Searching...
No Matches
PTextEdit.cpp
Go to the documentation of this file.
1/****************************************************************************
2
3 PTextEdit.cpp
4
5 Author: Andreas Suter
6 e-mail: andreas.suter@psi.ch
7
8*****************************************************************************/
9
10/***************************************************************************
11 * Copyright (C) 2010-2026 by Andreas Suter *
12 * andreas.suter@psi.ch *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28 ***************************************************************************/
29
92
93#include <iostream>
94#include <fstream>
95
96#include <QString>
97#include <QStringList>
98#include <QTextEdit>
99#include <QStatusBar>
100#include <QAction>
101#include <QMenuBar>
102#include <QMenu>
103#include <QToolBar>
104#include <QTabWidget>
105#include <QApplication>
106#include <QFontDatabase>
107#include <QComboBox>
108#include <QLineEdit>
109#include <QFileInfo>
110#include <QFile>
111#include <QFileDialog>
112#include <QtPrintSupport/QPrinter>
113#include <QtPrintSupport/QPrintDialog>
114#include <QColorDialog>
115#include <QPainter>
116#include <QMessageBox>
117#include <QDialog>
118#include <QTextCursor>
119#include <QTextBlock>
120#include <QTextDocumentFragment>
121#include <QTextList>
122#include <QProcess>
123#include <QFileSystemWatcher>
124#include <QDesktopServices>
125#include <QUrl>
126#include <QRegularExpression>
127#include <QElapsedTimer>
128#include <QThread>
129
130#include <QtDebug>
131
132#include "PTextEdit.h"
133#include "PSubTextEdit.h"
134#include "PAdmin.h"
135#include "PFindDialog.h"
136#include "PReplaceDialog.h"
138#include "PFitOutputHandler.h"
139#include "PDumpOutputHandler.h"
140#include "PPrefsDialog.h"
142#include "PMusrEditAbout.h"
143#include "PMsr2DataDialog.h"
144
145//----------------------------------------------------------------------------------------------------
156PTextEdit::PTextEdit( QWidget *parent )
157 : QMainWindow( parent )
158{
159 // reads and manages the conents of the xml-startup (musredit_startup.xml) file
160 fAdmin = std::make_unique<PAdmin>();
161
162 bool gotTheme = getTheme();
163
164 // set default setting of the fDarkMenuIconIcons only if a theme has been recognized, otherwise take the
165 // one from the xml startup file.
166 if (gotTheme) {
167 fAdmin->setDarkThemeIconsMenuFlag(fDarkMenuIcon);
168 fAdmin->setDarkThemeIconsToolbarFlag(fDarkToolBarIcon);
169 } else {
170 fDarkMenuIcon = fAdmin->getDarkThemeIconsMenuFlag();
171 fDarkToolBarIcon = fAdmin->getDarkThemeIconsToolbarFlag();
172 }
173
174 // keep the default editor width/height
175 fEditW = fAdmin->getEditWidth();
176 fEditH = fAdmin->getEditHeight();
177
178 // enable file system watcher. Needed to get notification if the msr-file is changed outside of musrfit at runtime
180 fFileSystemWatcher = std::make_unique<QFileSystemWatcher>();
181 if (fFileSystemWatcher == nullptr) {
182 QMessageBox::information(this, "ERROR", "Couldn't invoke QFileSystemWatcher!");
183 } else {
184 connect( fFileSystemWatcher.get(), SIGNAL(fileChanged(const QString&)), this, SLOT(fileChanged(const QString&)));
185 }
186
187 // initialize stuff
188 fMsr2DataParam = nullptr;
189 fFindReplaceData = nullptr;
190
191 // setup menus
198
199 fTabWidget = std::make_unique<QTabWidget>( this );
200 fTabWidget->setMovable(true); // allows to shuffle around tabs
201 setCentralWidget( fTabWidget.get() );
202
203 textFamily(fAdmin->getFontName());
204 textSize(QString("%1").arg(fAdmin->getFontSize()));
205
206 QString iconName("");
207 if (fDarkMenuIcon)
208 iconName = QString(":/icons/musrfit-dark.svg");
209 else
210 iconName = QString(":/icons/musrfit-plain.svg");
211 setWindowIcon( QIcon( iconName ) );
212
213 // if arguments are give, try to load those files, otherwise create an empty new file
214 if ( qApp->arguments().size() != 1 ) {
215 for ( int i = 1; i < qApp->arguments().size(); ++i )
216 load( qApp->arguments()[ i ] );
217 } else {
218 fileNew();
219 }
220
221 connect( fTabWidget.get(), SIGNAL( currentChanged(int) ), this, SLOT( applyFontSettings(int) ));
222
223 fLastDirInUse = fAdmin->getDefaultSavePath();
224
225 fStatusBar = this->statusBar();
226}
227
228//----------------------------------------------------------------------------------------------------
247{
248 if (fMsr2DataParam) {
249 delete fMsr2DataParam;
250 fMsr2DataParam = nullptr;
251 }
252 if (fFindReplaceData) {
253 delete fFindReplaceData;
254 fFindReplaceData = nullptr;
255 }
256}
257
258//----------------------------------------------------------------------------------------------------
278{
279 QToolBar *tb = new QToolBar( this );
280 tb->setWindowTitle( "File Actions" );
281 addToolBar( tb );
282
283 QMenu *menu = new QMenu( tr( "F&ile" ), this );
284 menuBar()->addMenu( menu );
285
286 QAction *a;
287 QString iconName("");
288
289 // New
290 if (fDarkMenuIcon)
291 iconName = QString(":/icons/document-new-dark.svg");
292 else
293 iconName = QString(":/icons/document-new-plain.svg");
294 a = new QAction( QIcon( iconName ), tr( "&New..." ), this );
295 a->setShortcut( tr("Ctrl+N") );
296 a->setStatusTip( tr("Create a new msr-file") );
297 connect( a, SIGNAL( triggered() ), this, SLOT( fileNew() ) );
298 menu->addAction(a);
299 fActions["New"] = a;
300
301 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
302 iconName = QString(":/icons/document-new-plain.svg");
303 a = new QAction( QIcon( iconName ), tr( "&New..." ), this );
304 connect( a, SIGNAL( triggered() ), this, SLOT( fileNew() ) );
305 }
306 tb->addAction(a);
307 fActions["New-tb"] = a;
308
309 // Open
310 if (fDarkMenuIcon)
311 iconName = QString(":/icons/document-open-dark.svg");
312 else
313 iconName = QString(":/icons/document-open-plain.svg");
314 a = new QAction( QIcon( iconName ), tr( "&Open..." ), this );
315 a->setShortcut( tr("Ctrl+O") );
316 a->setStatusTip( tr("Opens a msr-file") );
317 connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) );
318 menu->addAction(a);
319 fActions["Open"] = a;
320
321 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
322 iconName = QString(":/icons/document-open-plain.svg");
323 a = new QAction( QIcon( iconName ), tr( "&Open..." ), this );
324 connect( a, SIGNAL( triggered() ), this, SLOT( fileOpen() ) );
325 }
326 tb->addAction(a);
327 fActions["Open-tb"] = a;
328
329 // Recent Files
330 fRecentFilesMenu = menu->addMenu( tr("Recent Files") );
331 for (int i=0; i<MAX_RECENT_FILES; i++) {
332 fRecentFilesAction[i] = new QAction(fRecentFilesMenu);
333 fRecentFilesAction[i]->setVisible(false);
334 connect( fRecentFilesAction[i], SIGNAL(triggered()), this, SLOT(fileOpenRecent()));
336 }
338
339 // Reload
340 if (fDarkMenuIcon)
341 iconName = QString(":/icons/view-refresh-dark.svg");
342 else
343 iconName = QString(":/icons/view-refresh-plain.svg");
344 a = new QAction( QIcon( iconName ), tr( "Reload..." ), this );
345 a->setShortcut( tr("F5") );
346 a->setStatusTip( tr("Reload msr-file") );
347 connect( a, SIGNAL( triggered() ), this, SLOT( fileReload() ) );
348 menu->addAction(a);
349 fActions["Reload"] = a;
350
351 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
352 iconName = QString(":/icons/view-refresh-plain.svg");
353 a = new QAction( QIcon( iconName ), tr( "Reload..." ), this );
354 connect( a, SIGNAL( triggered() ), this, SLOT( fileReload() ) );
355 }
356 tb->addAction(a);
357 fActions["Reload-tb"] = a;
358
359 a = new QAction( tr( "Open Prefs..." ), this);
360 connect( a, SIGNAL( triggered() ), this, SLOT( fileOpenPrefs() ) );
361 menu->addAction(a);
362
363 menu->addSeparator();
364
365 // Save
366 if (fDarkMenuIcon)
367 iconName = QString(":/icons/document-save-dark.svg");
368 else
369 iconName = QString(":/icons/document-save-plain.svg");
370 a = new QAction( QIcon( iconName ), tr( "&Save..." ), this );
371 a->setShortcut( tr("Ctrl+S") );
372 a->setStatusTip( tr("Save msr-file") );
373 connect( a, SIGNAL( triggered() ), this, SLOT( fileSave() ) );
374 menu->addAction(a);
375 fActions["Save"] = a;
376
377 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
378 iconName = QString(":/icons/document-save-plain.svg");
379 a = new QAction( QIcon( iconName ), tr( "&Save..." ), this );
380 connect( a, SIGNAL( triggered() ), this, SLOT( fileSave() ) );
381 }
382 tb->addAction(a);
383 fActions["Save-tb"] = a;
384
385 // Save As
386 a = new QAction( tr( "Save &As..." ), this );
387 a->setStatusTip( tr("Save msr-file As") );
388 connect( a, SIGNAL( triggered() ), this, SLOT( fileSaveAs() ) );
389 menu->addAction(a);
390
391 // Save Prefs
392 a = new QAction( tr( "Save Prefs..." ), this );
393 a->setStatusTip( tr("Save the preferences") );
394 connect( a, SIGNAL( triggered() ), this, SLOT( fileSavePrefs() ) );
395 menu->addAction(a);
396
397 menu->addSeparator();
398
399 // Print
400 if (fDarkMenuIcon)
401 iconName = QString(":/icons/document-print-dark.svg");
402 else
403 iconName = QString(":/icons/document-print-plain.svg");
404 a = new QAction( QIcon( iconName ), tr( "&Print..." ), this );
405 a->setShortcut( tr("Ctrl+P") );
406 a->setStatusTip( tr("Print msr-file") );
407 connect( a, SIGNAL( triggered() ), this, SLOT( filePrint() ) );
408 menu->addAction(a);
409 fActions["Print"] = a;
410
411 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
412 iconName = QString(":/icons/document-print-plain.svg");
413 a = new QAction( QIcon( iconName ), tr( "&Print..." ), this );
414 connect( a, SIGNAL( triggered() ), this, SLOT( filePrint() ) );
415 }
416 tb->addAction(a);
417 fActions["Print-tb"] = a;
418
419 menu->addSeparator();
420
421 // Close
422 a = new QAction( tr( "&Close" ), this );
423 a->setShortcut( tr("Ctrl+W") );
424 a->setStatusTip( tr("Close msr-file") );
425 connect( a, SIGNAL( triggered() ), this, SLOT( fileClose() ) );
426 menu->addAction(a);
427
428 // Close All
429 a = new QAction( tr( "Close &All" ), this );
430 connect( a, SIGNAL( triggered() ), this, SLOT( fileCloseAll() ) );
431 menu->addAction(a);
432
433 // Close All Others
434 a = new QAction( tr( "Clo&se All Others" ), this );
435 a->setShortcut( tr("Ctrl+Shift+W") );
436 a->setStatusTip( tr("Close All Other Tabs") );
437 connect( a, SIGNAL( triggered() ), this, SLOT( fileCloseAllOthers() ) );
438 menu->addAction(a);
439
440 menu->addSeparator();
441
442 // Exit
443 a = new QAction( tr( "E&xit" ), this );
444 a->setShortcut( tr("Ctrl+Q") );
445 a->setStatusTip( tr("Exit Program") );
446 connect( a, SIGNAL( triggered() ), this, SLOT( fileExit() ) );
447 menu->addAction(a);
448}
449
450//----------------------------------------------------------------------------------------------------
460{
461 QToolBar *tb = new QToolBar( this );
462 tb->setWindowTitle( "Edit Actions" );
463 addToolBar( tb );
464
465 QMenu *menu = new QMenu( tr( "&Edit" ), this );
466 menuBar()->addMenu( menu );
467
468 QAction *a;
469 QString iconName("");
470
471 // Undo
472 if (fDarkMenuIcon)
473 iconName = QString(":/icons/edit-undo-dark.svg");
474 else
475 iconName = QString(":/icons/edit-undo-plain.svg");
476 a = new QAction( QIcon( iconName ), tr( "&Undo" ), this );
477 a->setShortcut( tr("Ctrl+Z") );
478 a->setStatusTip( tr("Edit Undo") );
479 connect( a, SIGNAL( triggered() ), this, SLOT( editUndo() ) );
480 menu->addAction(a);
481 fActions["Undo"] = a;
482
483 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
484 iconName = QString(":/icons/edit-undo-plain.svg");
485 a = new QAction( QIcon( iconName ), tr( "&Undo" ), this );
486 connect( a, SIGNAL( triggered() ), this, SLOT( editUndo() ) );
487 }
488 tb->addAction(a);
489 fActions["Undo-tb"] = a;
490
491 // Redo
492 if (fDarkMenuIcon)
493 iconName = QString(":/icons/edit-redo-dark.svg");
494 else
495 iconName = QString(":/icons/edit-redo-plain.svg");
496 a = new QAction( QIcon( iconName ), tr( "&Redo" ), this );
497 a->setShortcut( tr("Ctrl+Y") );
498 a->setStatusTip( tr("Edit Redo") );
499 connect( a, SIGNAL( triggered() ), this, SLOT( editRedo() ) );
500 menu->addAction(a);
501 fActions["Redo"] = a;
502
503 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
504 iconName = QString(":/icons/edit-redo-plain.svg");
505 a = new QAction( QIcon( iconName ), tr( "&Redo" ), this );
506 connect( a, SIGNAL( triggered() ), this, SLOT( editRedo() ) );
507 }
508 tb->addAction(a);
509 fActions["Redo-tb"] = a;
510
511 menu->addSeparator();
512
513 // Select All
514 a = new QAction( tr( "Select &All" ), this );
515 a->setShortcut( tr("Ctrl+A") );
516 a->setStatusTip( tr("Edit Select All") );
517 connect( a, SIGNAL( triggered() ), this, SLOT( editSelectAll() ) );
518 menu->addAction(a);
519
520 menu->addSeparator();
521 tb->addSeparator();
522
523 // Copy
524 if (fDarkMenuIcon)
525 iconName = QString(":/icons/edit-copy-dark.svg");
526 else
527 iconName = QString(":/icons/edit-copy-plain.svg");
528 a = new QAction( QIcon( iconName ), tr( "&Copy" ), this );
529 a->setShortcut( tr("Ctrl+C") );
530 a->setStatusTip( tr("Edit Copy") );
531 connect( a, SIGNAL( triggered() ), this, SLOT( editCopy() ) );
532 menu->addAction(a);
533 fActions["Copy"] = a;
534
535 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
536 iconName = QString(":/icons/edit-copy-plain.svg");
537 a = new QAction( QIcon( iconName ), tr( "&Copy" ), this );
538 connect( a, SIGNAL( triggered() ), this, SLOT( editCopy() ) );
539 }
540 tb->addAction(a);
541 fActions["Copy-tb"] = a;
542
543 // Cut
544 if (fDarkMenuIcon)
545 iconName = QString(":/icons/edit-cut-dark.svg");
546 else
547 iconName = QString(":/icons/edit-cut-plain.svg");
548 a = new QAction( QIcon( iconName ), tr( "Cu&t" ), this );
549 a->setShortcut( tr("Ctrl+X") );
550 a->setStatusTip( tr("Edit Cut") );
551 connect( a, SIGNAL( triggered() ), this, SLOT( editCut() ) );
552 menu->addAction(a);
553 fActions["Cut"] = a;
554
555 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
556 iconName = QString(":/icons/edit-cut-plain.svg");
557 a = new QAction( QIcon( iconName ), tr( "Cu&t" ), this );
558 connect( a, SIGNAL( triggered() ), this, SLOT( editCut() ) );
559 }
560 tb->addAction(a);
561 fActions["Cut-tb"] = a;
562
563 // Paste
564 if (fDarkMenuIcon)
565 iconName = QString(":/icons/edit-paste-dark.svg");
566 else
567 iconName = QString(":/icons/edit-paste-plain.svg");
568 a = new QAction( QIcon( iconName ), tr( "&Paste" ), this );
569 a->setShortcut( tr("Ctrl+V") );
570 a->setStatusTip( tr("Edit Paste") );
571 connect( a, SIGNAL( triggered() ), this, SLOT( editPaste() ) );
572 menu->addAction(a);
573 fActions["Paste"] = a;
574
575 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
576 iconName = QString(":/icons/edit-paste-plain.svg");
577 a = new QAction( QIcon( iconName ), tr( "&Paste" ), this );
578 connect( a, SIGNAL( triggered() ), this, SLOT( editPaste() ) );
579 }
580 tb->addAction(a);
581 fActions["Paste-tb"] = a;
582
583 menu->addSeparator();
584 tb->addSeparator();
585
586 // Find
587 if (fDarkMenuIcon)
588 iconName = QString(":/icons/edit-find-dark.svg");
589 else
590 iconName = QString(":/icons/edit-find-plain.svg");
591 a = new QAction( QIcon( iconName ), tr( "&Find" ), this );
592 a->setShortcut( tr("Ctrl+F") );
593 a->setStatusTip( tr("Edit Find") );
594 connect( a, SIGNAL( triggered() ), this, SLOT( editFind() ) );
595 menu->addAction(a);
596 fActions["Find"] = a;
597
598 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
599 iconName = QString(":/icons/edit-find-plain.svg");
600 a = new QAction( QIcon( iconName ), tr( "&Find" ), this );
601 connect( a, SIGNAL( triggered() ), this, SLOT( editFind() ) );
602 }
603 tb->addAction(a);
604 fActions["Find-tb"] = a;
605
606 // Find Next
607 if (fDarkMenuIcon)
608 iconName = QString(":/icons/go-next-use-dark.svg");
609 else
610 iconName = QString(":/icons/go-next-use-plain.svg");
611 a = new QAction( QIcon( iconName ), tr( "Find &Next" ), this );
612 a->setShortcut( tr("F3") );
613 a->setStatusTip( tr("Edit Find Next") );
614 connect( a, SIGNAL( triggered() ), this, SLOT( editFindNext() ) );
615 menu->addAction(a);
616 fActions["Find Next"] = a;
617
618 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
619 iconName = QString(":/icons/go-next-use-plain.svg");
620 a = new QAction( QIcon( iconName ), tr( "Find &Next" ), this );
621 connect( a, SIGNAL( triggered() ), this, SLOT( editFindNext() ) );
622 }
623 tb->addAction(a);
624 fActions["Find Next-tb"] = a;
625
626 // Find Previous
627 if (fDarkMenuIcon)
628 iconName = QString(":/icons/go-previous-use-dark.svg");
629 else
630 iconName = QString(":/icons/go-previous-use-plain.svg");
631 a = new QAction( QIcon( iconName ) , tr( "Find Pre&vious" ), this );
632 a->setShortcut( tr("Shift+F4") );
633 a->setStatusTip( tr("Edit Find Previous") );
634 connect( a, SIGNAL( triggered() ), this, SLOT( editFindPrevious() ) );
635 menu->addAction(a);
636 fActions["Find Previous"] = a;
637
638 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
639 iconName = QString(":/icons/go-previous-use-plain.svg");
640 a = new QAction( QIcon( iconName ), tr( "Find Pre&vious" ), this );
641 connect( a, SIGNAL( triggered() ), this, SLOT( editFindPrevious() ) );
642 }
643 tb->addAction(a);
644 fActions["Find Previous-tb"] = a;
645
646 // Replace
647 a = new QAction( tr( "Replace..." ), this );
648 a->setShortcut( tr("Ctrl+R") );
649 a->setStatusTip( tr("Edit Replace") );
650 connect( a, SIGNAL( triggered() ), this, SLOT( editFindAndReplace() ) );
651 menu->addAction(a);
652 menu->addSeparator();
653
654 QMenu *addSubMenu = new QMenu( tr ("Add Block"), this);
655
656 a = new QAction( tr("Title Block"), this );
657 a->setStatusTip( tr("Invokes MSR Title Block Dialog") );
658 connect( a, SIGNAL( triggered() ), this, SLOT( insertTitle() ));
659 addSubMenu->addAction(a);
660
661 a = new QAction( tr("Parameter Block"), this );
662 a->setStatusTip( tr("Invokes MSR Parameter Block Dialog") );
663 connect( a, SIGNAL( triggered() ), this, SLOT( insertParameterBlock() ));
664 addSubMenu->addAction(a);
665
666 a = new QAction( tr("Theory Block"), this );
667 a->setStatusTip( tr("Invokes MSR Theory Block Dialog") );
668 connect( a, SIGNAL( triggered() ), this, SLOT( insertTheoryBlock() ));
669 addSubMenu->addAction(a);
670
671 a = new QAction( tr("Function Block"), this );
672 a->setStatusTip( tr("Invokes MSR Function Block Dialog") );
673 connect( a, SIGNAL( triggered() ), this, SLOT( insertFunctionBlock() ));
674 addSubMenu->addAction(a);
675
676 // feed the theoryFunctions popup menu
677 QMenu *theoryFunctions = new QMenu( tr("Add Theory Function"), this );
678 for (unsigned int i=0; i<fAdmin->getTheoryCounts(); i++) {
679 PTheory *theoryItem = fAdmin->getTheoryItem(i);
680 a = new QAction( theoryItem->label, this);
681 theoryFunctions->addAction(a);
682 }
683 connect( theoryFunctions, SIGNAL( triggered(QAction*)), this, SLOT( insertTheoryFunction(QAction*) ) );
684
685 a = new QAction( tr("Asymmetry Run Block"), this );
686 a->setStatusTip( tr("Invokes MSR Asymmetry Run Block Dialog") );
687 connect( a, SIGNAL( triggered() ), this, SLOT( insertAsymRunBlock() ));
688 addSubMenu->addAction(a);
689
690 a = new QAction( tr("Single Histo Run Block"), this );
691 a->setStatusTip( tr("Invokes MSR Single Histo Run Block Dialog") );
692 connect( a, SIGNAL( triggered() ), this, SLOT( insertSingleHistRunBlock() ));
693 addSubMenu->addAction(a);
694
695 a = new QAction( tr("NonMuSR Run Block"), this );
696 a->setStatusTip( tr("Invokes MSR NonMuSR Run Block Dialog") );
697 connect( a, SIGNAL( triggered() ), this, SLOT( insertNonMusrRunBlock() ));
698 addSubMenu->addAction(a);
699
700 a = new QAction( tr("Command Block"), this );
701 a->setStatusTip( tr("Invokes MSR Command Block Dialog") );
702 connect( a, SIGNAL( triggered() ), this, SLOT( insertCommandBlock() ));
703 addSubMenu->addAction(a);
704
705 a = new QAction( tr("Fourier Block"), this );
706 a->setStatusTip( tr("Invokes MSR Fourier Block Dialog") );
707 connect( a, SIGNAL( triggered() ), this, SLOT( insertFourierBlock() ));
708 addSubMenu->addAction(a);
709
710 a = new QAction( tr("Plot Block"), this );
711 a->setStatusTip( tr("Invokes MSR Plot Block Dialog") );
712 connect( a, SIGNAL( triggered() ), this, SLOT( insertPlotBlock() ));
713 addSubMenu->addAction(a);
714
715 a = new QAction( tr("Statistic Block"), this );
716 a->setStatusTip( tr("Invokes MSR Statistic Block Dialog") );
717 connect( a, SIGNAL( triggered() ), this, SLOT( insertStatisticBlock() ));
718 addSubMenu->addAction(a);
719
720 menu->addMenu(addSubMenu);
721 menu->addMenu(theoryFunctions);
722 menu->addSeparator();
723
724 a = new QAction( tr( "Co&mment" ), this );
725 a->setShortcut( tr("Ctrl+M") );
726 a->setStatusTip( tr("Edit Comment Selected Lines") );
727 connect( a, SIGNAL( triggered() ), this, SLOT( editComment() ) );
728 menu->addAction(a);
729
730 a = new QAction( tr( "Unco&mment" ), this );
731 a->setShortcut( tr("Ctrl+Shift+M") );
732 a->setStatusTip( tr("Edit Uncomment Selected Lines") );
733 connect( a, SIGNAL( triggered() ), this, SLOT( editUncomment() ) );
734 menu->addAction(a);
735}
736
737//----------------------------------------------------------------------------------------------------
746{
747 QToolBar *tb = new QToolBar( this );
748 tb->setWindowTitle( "Format Actions" );
749 addToolBar( tb );
750
751 fComboFont = std::make_unique<QComboBox>();
752 fComboFont->setEditable(true);
753 fComboFont->addItems( QFontDatabase::families() );
754 connect( fComboFont.get(), SIGNAL( currentTextChanged( const QString & ) ),
755 this, SLOT( textFamily( const QString & ) ) );
756 QLineEdit *edit = fComboFont->lineEdit();
757 if (edit == nullptr) {
758 return;
759 }
760 edit->setText( fAdmin->getFontName() );
761 tb->addWidget(fComboFont.get());
762
763 fComboSize = std::make_unique<QComboBox>( tb );
764 fComboSize->setEditable(true);
765 QList<int> sizes = QFontDatabase::standardSizes();
766 QList<int>::Iterator it = sizes.begin();
767 for ( ; it != sizes.end(); ++it )
768 fComboSize->addItem( QString::number( *it ) );
769 connect( fComboSize.get(), SIGNAL( currentTextChanged( const QString & ) ),
770 this, SLOT( textSize( const QString & ) ) );
771 edit = fComboSize->lineEdit();
772 if (edit == nullptr) {
773 return;
774 }
775 edit->setText( QString("%1").arg(fAdmin->getFontSize()) );
776 tb->addWidget(fComboSize.get());
777}
778
779//----------------------------------------------------------------------------------------------------
791{
792 addToolBarBreak();
793
794 QToolBar *tb = new QToolBar( this );
795 tb->setWindowTitle( "Musr Actions" );
796 addToolBar( tb );
797
798 QMenu *menu = new QMenu( tr( "&MusrFit" ), this );
799 menuBar()->addMenu( menu );
800
801 QAction *a;
802 QString iconName("");
803
804 // musrWiz
805 if (fDarkMenuIcon)
806 iconName = QString(":/icons/musrWiz-32x32-dark.svg");
807 else
808 iconName = QString(":/icons/musrWiz-32x32.svg");
809 a = new QAction( QIcon( iconName ), tr( "musr&Wiz" ), this );
810 a->setShortcut( tr("Alt+W") );
811 a->setStatusTip( tr("Call musrWiz which helps to create msr-files - currently still very limited") );
812 connect( a, SIGNAL( triggered() ), this, SLOT( musrWiz() ) );
813 menu->addAction(a);
814 fActions["musrWiz"] = a;
815
816 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
817 iconName = QString(":/icons/musrWiz-32x32.svg");
818 a = new QAction( QIcon( iconName ), tr( "musr&Wiz" ), this );
819 connect( a, SIGNAL( triggered() ), this, SLOT( musrWiz() ) );
820 }
821 tb->addAction(a);
822 fActions["musrWiz-tb"] = a;
823
824 menu->addSeparator();
825 tb->addSeparator();
826
827 // Calculate Chisq
828 if (fDarkMenuIcon)
829 iconName = QString(":/icons/musrchisq-dark.svg");
830 else
831 iconName = QString(":/icons/musrchisq-plain.svg");
832 a = new QAction( QIcon( iconName ), tr( "Calculate &Chisq" ), this );
833 a->setShortcut( tr("Alt+C") );
834 a->setStatusTip( tr("Calculate Chi Square (Log Max Likelihood)") );
835 connect( a, SIGNAL( triggered() ), this, SLOT( musrCalcChisq() ) );
836 menu->addAction(a);
837 fActions["calcChisq"] = a;
838
839 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
840 iconName = QString(":/icons/musrchisq-plain.svg");
841 a = new QAction( QIcon( iconName ), tr( "Calculate &Chisq" ), this );
842 connect( a, SIGNAL( triggered() ), this, SLOT( musrCalcChisq() ) );
843 }
844 tb->addAction(a);
845 fActions["calcChisq-tb"] = a;
846
847 // musrfit
848 if (fDarkMenuIcon)
849 iconName = QString(":/icons/musrfit-dark.svg");
850 else
851 iconName = QString(":/icons/musrfit-plain.svg");
852 a = new QAction( QIcon( iconName ), tr( "&Fit" ), this );
853 a->setShortcut( tr("Alt+F") );
854 a->setStatusTip( tr("Fit") );
855 connect( a, SIGNAL( triggered() ), this, SLOT( musrFit() ) );
856 menu->addAction(a);
857 fActions["musrfit"] = a;
858
859 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
860 iconName = QString(":/icons/musrfit-plain.svg");
861 a = new QAction( QIcon( iconName ), tr( "&Fit" ), this );
862 connect( a, SIGNAL( triggered() ), this, SLOT( musrFit() ) );
863 }
864 tb->addAction(a);
865 fActions["musrfit-tb"] = a;
866
867 // Swap Msr/Mlog
868 if (fDarkMenuIcon)
869 iconName = QString(":/icons/musrswap-dark.svg");
870 else
871 iconName = QString(":/icons/musrswap-plain.svg");
872 a = new QAction( QIcon( iconName ), tr( "&Swap Msr <-> Mlog" ), this );
873 a->setShortcut( tr("Alt+S") );
874 a->setStatusTip( tr("Swap msr-file <-> mlog-file") );
875 connect( a, SIGNAL( triggered() ), this, SLOT( musrSwapMsrMlog() ) );
876 menu->addAction(a);
877 fActions["Swap Msr/Mlog"] = a;
878
879 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
880 iconName = QString(":/icons/musrswap-plain.svg");
881 a = new QAction( QIcon( iconName ), tr( "&Swap Msr <-> Mlog" ), this );
882 connect( a, SIGNAL( triggered() ), this, SLOT( musrSwapMsrMlog() ) );
883 }
884 tb->addAction(a);
885 fActions["Swap Msr/Mlog-tb"] = a;
886
887 // musrStep
888 if (fDarkMenuIcon)
889 iconName = QString(":/icons/musrStep-32x32-dark.svg");
890 else
891 iconName = QString(":/icons/musrStep-32x32.svg");
892 a = new QAction( QIcon( iconName ), tr( "Set Ste&ps" ), this );
893 a->setShortcut( tr("Alt+P") );
894 a->setStatusTip( tr("Set Steps") );
895 connect( a, SIGNAL( triggered() ), this, SLOT( musrSetSteps() ) );
896 menu->addAction(a);
897 fActions["musrStep"] = a;
898
899 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
900 iconName = QString(":/icons/musrStep-32x32.svg");
901 a = new QAction( QIcon( iconName ), tr( "Set Ste&ps" ), this );
902 connect( a, SIGNAL( triggered() ), this, SLOT( musrSetSteps() ) );
903 }
904 tb->addAction(a);
905 fActions["musrStep-tb"] = a;
906
907 // msr2data
908 if (fDarkMenuIcon)
909 iconName = QString(":/icons/msr2data-dark.svg");
910 else
911 iconName = QString(":/icons/msr2data-plain.svg");
912 a = new QAction( QIcon( iconName ), tr( "Msr&2Data" ), this );
913 a->setShortcut( tr("Alt+2") );
914 a->setStatusTip( tr("Start msr2data interface") );
915 connect( a, SIGNAL( triggered() ), this, SLOT( musrMsr2Data() ) );
916 menu->addAction(a);
917 fActions["msr2data"] = a;
918
919 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
920 iconName = QString(":/icons/msr2data-plain.svg");
921 a = new QAction( QIcon( iconName ), tr( "&Msr2Data" ), this );
922 connect( a, SIGNAL( triggered() ), this, SLOT( musrMsr2Data() ) );
923 }
924 tb->addAction(a);
925 fActions["msr2data-tb"] = a;
926
927 // mupp
928 if (fDarkMenuIcon)
929 iconName = QString(":/icons/mupp-dark.svg");
930 else
931 iconName = QString(":/icons/mupp-plain.svg");
932 a = new QAction( QIcon( iconName ), tr( "m&upp" ), this );
933 a->setShortcut( tr("Alt+U") );
934 a->setStatusTip( tr("Start mupp, the muSR parameter plotter") );
935 connect( a, SIGNAL( triggered() ), this, SLOT( mupp() ) );
936 menu->addAction(a);
937 fActions["mupp"] = a;
938
939 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
940 iconName = QString(":/icons/mupp-plain.svg");
941 a = new QAction( QIcon( iconName ), tr( "m&upp" ), this );
942 connect( a, SIGNAL( triggered() ), this, SLOT( mupp() ) );
943 }
944 tb->addAction(a);
945 fActions["mupp-tb"] = a;
946
947 // musrView2dat
948 if (fDarkMenuIcon)
949 iconName = QString(":/icons/musrview2dat-dark.svg");
950 else
951 iconName = QString(":/icons/musrview2dat-plain.svg");
952 a = new QAction( QIcon( iconName ), tr( "View2Dat" ), this );
953 a->setStatusTip( tr("Export musrview data from a collection of msr-files.") );
954 connect( a, SIGNAL( triggered() ), this, SLOT( musrView2Dat() ) );
955 menu->addAction(a);
956 fActions["musrview2dat"] = a;
957
958 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
959 iconName = QString(":/icons/musrview2dat-plain.svg");
960 a = new QAction( QIcon( iconName ), tr( "View2Dat" ), this );
961 connect( a, SIGNAL( triggered() ), this, SLOT( musrView2Dat() ) );
962 }
963 tb->addAction(a);
964 fActions["musrview2dat-tb"] = a;
965
966 menu->addSeparator();
967 tb->addSeparator();
968
969 // musrview
970 if (fDarkMenuIcon)
971 iconName = QString(":/icons/musrview-dark.svg");
972 else
973 iconName = QString(":/icons/musrview-plain.svg");
974 a = new QAction( QIcon( iconName ), tr( "&View" ), this );
975 a->setShortcut( tr("Alt+V") );
976 a->setStatusTip( tr("Start musrview") );
977 connect( a, SIGNAL( triggered() ), this, SLOT( musrView() ) );
978 menu->addAction(a);
979 fActions["musrview"] = a;
980
981 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
982 iconName = QString(":/icons/musrview-plain.svg");
983 a = new QAction( QIcon( iconName ), tr( "&View" ), this );
984 connect( a, SIGNAL( triggered() ), this, SLOT( musrView() ) );
985 }
986 tb->addAction(a);
987 fActions["musrview-tb"] = a;
988
989 // musrt0
990 if (fDarkMenuIcon)
991 iconName = QString(":/icons/musrt0-dark.svg");
992 else
993 iconName = QString(":/icons/musrt0-plain.svg");
994 fMusrT0Action = std::make_unique<QAction>( QIcon( iconName ), tr( "&T0" ), this );
995 fMusrT0Action->setStatusTip( tr("Start musrt0") );
996 connect( fMusrT0Action.get(), SIGNAL( triggered() ), this, SLOT( musrT0() ) );
997 menu->addAction(fMusrT0Action.get());
998 fActions["musrt0"] = fMusrT0Action.get();
999 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
1000 iconName = QString(":/icons/musrt0-plain.svg");
1001 a = new QAction( QIcon( iconName ), tr( "&T0" ), this );
1002 connect( a, SIGNAL( triggered() ), this, SLOT( musrT0() ) );
1003 }
1004 tb->addAction(fMusrT0Action.get());
1005 fMusrT0Action->setEnabled(fAdmin->getEnableMusrT0Flag());
1006 fActions["musrt0-tb"] = fMusrT0Action.get();
1007
1008 // musrFT
1009 if (fDarkMenuIcon)
1010 iconName = QString(":/icons/musrFT-dark.svg");
1011 else
1012 iconName = QString(":/icons/musrFT-plain.svg");
1013 a = new QAction( QIcon( iconName ), tr( "Raw Fourier" ), this );
1014 a->setStatusTip( tr("Start musrFT") );
1015 connect( a, SIGNAL( triggered() ), this, SLOT( musrFT() ) );
1016 menu->addAction(a);
1017 fActions["musrFT"] = a;
1018
1019 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
1020 iconName = QString(":/icons/musrFT-plain.svg");
1021 a = new QAction( QIcon( iconName ), tr( "Raw Fourier" ), this );
1022 connect( a, SIGNAL( triggered() ), this, SLOT( musrFT() ) );
1023 }
1024 tb->addAction(a);
1025 fActions["musrFT-tb"] = a;
1026
1027 // musrprefs
1028 if (fDarkMenuIcon)
1029 iconName = QString(":/icons/musrprefs-dark.svg");
1030 else
1031 iconName = QString(":/icons/musrprefs-plain.svg");
1032 a = new QAction( QIcon( iconName ), tr( "&Preferences" ), this );
1033 a->setStatusTip( tr("Show Preferences") );
1034 connect( a, SIGNAL( triggered() ), this, SLOT( musrPrefs() ) );
1035 menu->addAction(a);
1036 fActions["musrprefs"] = a;
1037
1038 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
1039 iconName = QString(":/icons/musrprefs-plain.svg");
1040 a = new QAction( QIcon( iconName ), tr( "&Preferences" ), this );
1041 connect( a, SIGNAL( triggered() ), this, SLOT( musrPrefs() ) );
1042 }
1043 tb->addAction(a);
1044 fActions["musrprefs-tb"] = a;
1045
1046 menu->addSeparator();
1047 tb->addSeparator();
1048
1049 // musrdump
1050 if (fDarkMenuIcon)
1051 iconName = QString(":/icons/musrdump-dark.svg");
1052 else
1053 iconName = QString(":/icons/musrdump-plain.svg");
1054 a = new QAction( QIcon( iconName), tr( "&Dump Header"), this);
1055 a->setStatusTip( tr("Dumps muSR File Header Information") );
1056 connect( a, SIGNAL(triggered()), this, SLOT(musrDump()));
1057 menu->addAction(a);
1058 fActions["musrdump"] = a;
1059 if (!fDarkToolBarIcon) { // tool bar icon is not dark, even though the theme is (ubuntu)
1060 iconName = QString(":/icons/musrdump-plain.svg");
1061 a = new QAction( QIcon( iconName ), tr( "&Dump Header" ), this );
1062 connect( a, SIGNAL( triggered() ), this, SLOT( musrDump() ) );
1063 }
1064 tb->addAction(a);
1065 fActions["musrdump-tb"] = a;
1066}
1067
1068//----------------------------------------------------------------------------------------------------
1077{
1078 QMenu *menu = new QMenu( tr( "&Help" ), this );
1079 menuBar()->addMenu( menu);
1080
1081 QAction *a;
1082 a = new QAction(tr( "Contents ..." ), this );
1083 a->setStatusTip( tr("Help Contents") );
1084 connect( a, SIGNAL( triggered() ), this, SLOT( helpContents() ));
1085 menu->addAction(a);
1086
1087 a = new QAction(tr( "Author(s) ..." ), this );
1088 a->setStatusTip( tr("Help About") );
1089 connect( a, SIGNAL( triggered() ), this, SLOT( helpAbout() ));
1090 menu->addAction(a);
1091
1092 a = new QAction(tr( "About Qt..." ), this );
1093 a->setStatusTip( tr("Help About Qt") );
1094 connect( a, SIGNAL( triggered() ), this, SLOT( helpAboutQt() ));
1095 menu->addAction(a);
1096}
1097
1098//----------------------------------------------------------------------------------------------------
1103{
1104 QToolBar *tb = new QToolBar( this );
1105 tb->setWindowTitle( "JumpToBlock Actions" );
1106 addToolBar( tb );
1107
1108 QStringList jumpToBlockStr = {"FITPARAMETER", "THEORY", "FUNCTIONS", "GLOBAL", "RUN", "COMMANDS", "PLOT", "FOURIER", "STATISTIC"};
1109 fJumpToBlock = std::make_unique<QComboBox>();
1110 if (fJumpToBlock == nullptr)
1111 return;
1112 fJumpToBlock->addItems(jumpToBlockStr);
1113 fJumpToBlock->setEditable(false);
1114
1115 connect( fJumpToBlock.get(), SIGNAL( activated(int) ), this, SLOT( jumpToBlock(int) ));
1116
1117 QLabel *jstr = new QLabel(" Jump to block: ");
1118
1119 tb->addWidget(jstr);
1120 tb->addWidget(fJumpToBlock.get());
1121}
1122
1123//----------------------------------------------------------------------------------------------------
1130void PTextEdit::load( const QString &f, const int index )
1131{
1132 // check if the file exists
1133 if ( !QFile::exists( f ) )
1134 return;
1135
1136 // create a new text edit object
1137 PSubTextEdit *edit = new PSubTextEdit( fAdmin.get() );
1138 edit->setFont(QFont(fAdmin->getFontName(), fAdmin->getFontSize()));
1139 edit->setCenterOnScroll(true);
1140
1141 // place the text edit object at the appropriate tab position
1142 if (index == -1)
1143 fTabWidget->addTab( edit, QFileInfo( f ).fileName() );
1144 else
1145 fTabWidget->insertTab( index, edit, QFileInfo( f ).fileName() );
1146 QFile file( f );
1147 if ( !file.open( QIODevice::ReadOnly ) )
1148 return;
1149
1150 // add file name to recent file names
1151 fAdmin->addRecentFile(QFileInfo(f).absoluteFilePath()); // keep it in admin
1152 fillRecentFiles(); // update menu
1153
1154 // add the msr-file to the file system watchersssss
1155 fFileSystemWatcher->addPath(f);
1156
1157 // read the file
1158 QTextStream ts( &file );
1159 QString txt = ts.readAll();
1160 edit->setPlainText( txt );
1161 doConnections( edit ); // add all necessary signal/slot connections
1162
1163 // set the tab widget to the current tab
1164 fTabWidget->setCurrentIndex(fTabWidget->indexOf(edit));
1165 edit->viewport()->setFocus();
1166
1167 // update the filename mapper
1168 fFilenames.remove( edit );
1169 fFilenames.insert( edit, f );
1170}
1171
1172//----------------------------------------------------------------------------------------------------
1177{
1178 if (fTabWidget == nullptr)
1179 return nullptr;
1180
1181 if ( fTabWidget->currentWidget() ) {
1182 if (fTabWidget->currentWidget()->inherits( "PSubTextEdit" )) {
1183 return dynamic_cast<PSubTextEdit*>(fTabWidget->currentWidget());
1184 }
1185 }
1186
1187 return nullptr;
1188}
1189
1190//----------------------------------------------------------------------------------------------------
1197{
1198// connect( e, SIGNAL( currentFontChanged( const QFont & ) ),
1199// this, SLOT( fontChanged( const QFont & ) ) );
1200
1201 connect( e, SIGNAL( textChanged() ), this, SLOT( textChanged() ));
1202
1203 connect( e, SIGNAL( cursorPositionChanged() ), this, SLOT( currentCursorPosition() ));
1204}
1205
1206//----------------------------------------------------------------------------------------------------
1214
1215//----------------------------------------------------------------------------------------------------
1223
1224//----------------------------------------------------------------------------------------------------
1232
1233//----------------------------------------------------------------------------------------------------
1240{
1241 currentEditor()->insertTheoryFunction(a->text());
1242}
1243
1244//----------------------------------------------------------------------------------------------------
1252
1253//----------------------------------------------------------------------------------------------------
1261
1262//----------------------------------------------------------------------------------------------------
1270
1271//----------------------------------------------------------------------------------------------------
1279
1280//----------------------------------------------------------------------------------------------------
1288
1289//----------------------------------------------------------------------------------------------------
1297
1298//----------------------------------------------------------------------------------------------------
1306
1307//----------------------------------------------------------------------------------------------------
1315
1316//----------------------------------------------------------------------------------------------------
1321{
1322 PSubTextEdit *edit = new PSubTextEdit( fAdmin.get() );
1323 edit->setFont(QFont(fAdmin->getFontName(), fAdmin->getFontSize()));
1324 edit->setCenterOnScroll(true);
1325 doConnections( edit );
1326 fTabWidget->addTab( edit, tr( "noname" ) );
1327 fTabWidget->setCurrentIndex(fTabWidget->indexOf(edit));
1328 fFilenames.insert(edit, tr("noname"));
1329 edit->viewport()->setFocus();
1330}
1331
1332//----------------------------------------------------------------------------------------------------
1339{
1340 QStringList flns = QFileDialog::getOpenFileNames( this, tr("Open msr-/mlog-File"),
1342 tr( "msr-Files (*.msr);;msr-Files (*.msr *.mlog);;All Files (*)" ));
1343
1344 QStringList::Iterator it = flns.begin();
1345 QFileInfo finfo1;
1346 bool alreadyOpen = false;
1347 int idx;
1348
1349 // if flns are present, keep the corresponding directory
1350 if (flns.size() > 0) {
1351 finfo1.setFile(flns.at(0));
1352 fLastDirInUse = finfo1.absoluteFilePath();
1353 }
1354
1355 while( it != flns.end() ) {
1356 // check if the file is not already open
1357 finfo1.setFile(*it);
1358 alreadyOpen = fileAlreadyOpen(finfo1, idx);
1359
1360 if (!alreadyOpen) {
1361 load(*it);
1362 } else {
1363 fTabWidget->setCurrentIndex(idx);
1364 fileReload();
1365 }
1366
1367 ++it;
1368 }
1369
1370 // in case there is a 1st empty tab "noname", remove it
1371 QString tabStr = fTabWidget->tabText(0);
1372 tabStr.remove('&'); // this is needed since the QTabWidget adds short-cut info as '&' to the tab name
1373 if (tabStr == "noname") { // has to be the first, otherwise do nothing
1374 fFileSystemWatcher->removePath("noname");
1375
1376 delete fTabWidget->widget(0);
1377 }
1378}
1379
1380//----------------------------------------------------------------------------------------------------
1385{
1386 QAction *action = qobject_cast<QAction *>(sender());
1387
1388 if (action) {
1389 // check if this file is already open and if so, switch the tab
1390 QFileInfo finfo1, finfo2;
1391 QString tabFln;
1392 bool alreadyOpen = false;
1393 QString fln = action->text();
1394 fln.remove('&');
1395 finfo1.setFile(fln);
1396
1397 for (int i=0; i<fTabWidget->count(); i++) {
1398 tabFln = *fFilenames.find( dynamic_cast<PSubTextEdit*>(fTabWidget->widget(i)));
1399 finfo2.setFile(tabFln);
1400 if (finfo1.absoluteFilePath() == finfo2.absoluteFilePath()) {
1401 alreadyOpen = true;
1402 fTabWidget->setCurrentIndex(i);
1403 break;
1404 }
1405 }
1406
1407 if (!alreadyOpen) {
1408 // make sure the file exists
1409 if (!finfo1.exists()) {
1410 QMessageBox::critical(this, "ERROR", QString("File '%1' does not exist.\nWill not do anything.").arg(fln));
1411 return;
1412 }
1413 load(fln);
1414 } else {
1415 fileReload();
1416 }
1417
1418 // in case there is a 1st empty tab "noname", remove it
1419 fln = fTabWidget->tabText(0);
1420 fln.remove("&");
1421 if (fln == "noname") { // has to be the first, otherwise do nothing
1422 fFileSystemWatcher->removePath("noname");
1423
1424 delete fTabWidget->widget(0);
1425 }
1426 }
1427}
1428
1429//----------------------------------------------------------------------------------------------------
1434{
1435 if ( fFilenames.find( currentEditor() ) == fFilenames.end() ) {
1436 QMessageBox::critical(this, "ERROR", "Cannot reload a file not previously saved ;-)");
1437 } else {
1438 int index = fTabWidget->currentIndex();
1439 QString fln = *fFilenames.find( currentEditor() );
1440 fileClose(false);
1441 load(fln, index);
1442 }
1443}
1444
1445//----------------------------------------------------------------------------------------------------
1450{
1451 QString fln("");
1452 QString msg("");
1453 QMessageBox msgBox;
1454 msgBox.setText("Which Preferences do you want to open?");
1455 msgBox.addButton("Default", QMessageBox::AcceptRole);
1456 msgBox.addButton("Custom", QMessageBox::AcceptRole);
1457 msgBox.setStandardButtons(QMessageBox::Cancel);
1458 int result = msgBox.exec();
1459 if (result == QMessageBox::Cancel) {
1460 return;
1461 } else if (result == 0) { // default dir
1462 fln = fAdmin->getDefaultPrefPathName();
1463 msg = QString("Current Default Preferences Path-Name:\n") + fln;
1464 if (QMessageBox::information(this, "INFO", msg, QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Cancel)
1465 return;
1466 } else if (result == 1) { // custom dir
1467 fln = QFileDialog::getOpenFileName( this, tr("Open Prefs"),
1469 tr( "xml-Files (*.xml);; All Files (*)" ));
1470 }
1471
1472 if (fAdmin->loadPrefs(fln)) {
1473 msg = QString("Prefs from '") + fln + QString("' loaded.");
1474 QMessageBox::information(nullptr, "INFO", msg);
1475 }
1476
1477 // make sure that dark/plain icon scheme is properly loaded
1478 if (getTheme()) {
1481 }
1482
1483 if (fAdmin->getDarkThemeIconsMenuFlag() != fDarkMenuIcon) {
1486 }
1487
1488 if (fAdmin->getDarkThemeIconsToolbarFlag() != fDarkToolBarIcon) {
1491 }
1492}
1493
1494//----------------------------------------------------------------------------------------------------
1499{
1500 if ( !currentEditor() )
1501 return;
1502
1504
1505 if ( *fFilenames.find( currentEditor() ) == QString("noname") ) {
1506 fileSaveAs();
1507 } else {
1508 QFile file( *fFilenames.find( currentEditor() ) );
1509 if ( !file.open( QIODevice::WriteOnly ) ) {
1510 QMessageBox::critical(this, "ERROR", "Couldn't save the file!\nDisk full?\nNo write access?");
1511 return;
1512 }
1513 QTextStream ts( &file );
1514 ts << currentEditor()->toPlainText();
1515
1516 // remove trailing '*' modification indicators
1517 QString fln = *fFilenames.find( currentEditor() );
1518 fTabWidget->setTabText(fTabWidget->indexOf( currentEditor() ), QFileInfo(fln).fileName());
1519 }
1520
1521 fileSystemWatcherActivation(); // delayed activation of fFileSystemWatcherActive
1522}
1523
1524//----------------------------------------------------------------------------------------------------
1530{
1531 if ( !currentEditor() )
1532 return;
1533
1535
1536 QString fn = QFileDialog::getSaveFileName( this,
1537 tr( "Save msr-/mlog-file As" ), *fFilenames.find( currentEditor() ),
1538 tr( "msr-Files (*.msr *.mlog);;All Files (*)" ) );
1539 if ( !fn.isEmpty() ) {
1540 fFilenames.remove( currentEditor() );
1541 fFilenames.insert( currentEditor(), fn );
1542 fileSave();
1543 }
1544
1545 fileSystemWatcherActivation(); // delayed activation of fFileSystemWatcherActive
1546}
1547
1548//----------------------------------------------------------------------------------------------------
1553{
1554 QString fln("");
1555 QString msg("");
1556 QMessageBox msgBox;
1557 msgBox.setText("Which Preferences do you want to open?");
1558 QAbstractButton *def = msgBox.addButton("Default", QMessageBox::AcceptRole);
1559 QAbstractButton *cust = msgBox.addButton("Custom", QMessageBox::AcceptRole);
1560 msgBox.setStandardButtons(QMessageBox::Cancel);
1561 int result = msgBox.exec();
1562 if (result == QMessageBox::Cancel) {
1563 return;
1564 } else if (msgBox.clickedButton() == def) { // default dir
1565 fln = fAdmin->getDefaultPrefPathName();
1566 msg = QString("Current Default Preferences Path-Name:\n") + fln;
1567 if (QMessageBox::information(this, "INFO", msg, QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Cancel)
1568 return;
1569 } else if (msgBox.clickedButton() == cust) { // custom dir
1570 fln = QFileDialog::getSaveFileName( this,
1571 tr( "Save Prefs As" ), "musredit_startup.xml",
1572 tr( "xml-Files (*.xml);;All Files (*)" ) );
1573 }
1574
1575 if ( !fln.isEmpty() ) {
1576 fAdmin->savePrefs(fln);
1577 msg = QString("Prefs to '") + fln + QString("' saved.");
1578 QMessageBox::information(nullptr, "INFO", msg);
1579 }
1580}
1581
1582//----------------------------------------------------------------------------------------------------
1587{
1588 if ( !currentEditor() )
1589 return;
1590#ifndef QT_NO_PRINTER
1591 QPrinter printer( QPrinter::HighResolution );
1592 printer.setFullPage(true);
1593 QPrintDialog dialog(&printer, this);
1594 if (dialog.exec()) { // printer dialog
1595 statusBar()->showMessage( "Printing..." );
1596
1597 QPainter p( &printer );
1598 // Check that there is a valid device to print to.
1599 if ( !p.device() )
1600 return;
1601
1602 QFont font( currentEditor()->QWidget::font() );
1603 font.setPointSize( 10 ); // we define 10pt to be a nice base size for printing
1604 p.setFont( font );
1605
1606 int yPos = 0; // y-position for each line
1607 QFontMetrics fm = p.fontMetrics();
1608 int dpiy = printer.logicalDpiY();
1609 int margin = static_cast<int>( (2/2.54)*dpiy ); // 2 cm margins
1610
1611 // print msr-file
1612 QString fln = *fFilenames.find(currentEditor());
1613 QString header1(fln);
1614 QFileInfo flnInfo(fln);
1615 QString header2 = QString("last modified: ") + flnInfo.lastModified().toString("dd.MM.yyyy - hh:mm:ss");
1616 QString line("-------------------------------------");
1617 QStringList strList = currentEditor()->toPlainText().split("\n");
1618 for (QStringList::Iterator it = strList.begin(); it != strList.end(); ++it) {
1619 // new page needed?
1620 if ( margin + yPos > printer.height() - margin ) {
1621 printer.newPage(); // no more room on this page
1622 yPos = 0; // back to top of page
1623 }
1624
1625 if (yPos == 0) { // print header
1626 font.setPointSize( 8 );
1627 p.setFont( font );
1628
1629 p.drawText(margin, margin+yPos, printer.width(), fm.lineSpacing(),
1630 Qt::TextExpandTabs | Qt::TextDontClip, header1);
1631 yPos += fm.lineSpacing();
1632 p.drawText(margin, margin+yPos, printer.width(), fm.lineSpacing(),
1633 Qt::TextExpandTabs | Qt::TextDontClip, header2);
1634 yPos += fm.lineSpacing();
1635 p.drawText(margin, margin+yPos, printer.width(), fm.lineSpacing(),
1636 Qt::TextExpandTabs | Qt::TextDontClip, line);
1637 yPos += 1.5*fm.lineSpacing();
1638
1639 font.setPointSize( 10 );
1640 p.setFont( font );
1641 }
1642
1643 // print data
1644 p.drawText(margin, margin+yPos, printer.width(), fm.lineSpacing(),
1645 Qt::TextExpandTabs | Qt::TextDontClip, *it);
1646 yPos += fm.lineSpacing();
1647 }
1648
1649 p.end();
1650 }
1651#endif
1652}
1653
1654//----------------------------------------------------------------------------------------------------
1661void PTextEdit::fileClose(const bool check)
1662{
1663 // first check if there is any tab present
1664 if (fTabWidget->count()==0) // no tabs present
1665 return;
1666
1667 // check if the has modification
1668 int idx = fTabWidget->currentIndex();
1669
1670 if ((fTabWidget->tabText(idx).indexOf("*")>0) && check) {
1671 int result = QMessageBox::warning(this, "WARNING",
1672 "Do you really want to close this file.\nChanges will be lost",
1673 QMessageBox::Close, QMessageBox::Cancel);
1674 if (result == QMessageBox::Cancel)
1675 return;
1676 }
1677
1678 QString str = *fFilenames.find(currentEditor());
1679 fFileSystemWatcher->removePath(str);
1680
1681 delete currentEditor();
1682
1683 if ( currentEditor() )
1684 currentEditor()->viewport()->setFocus();
1685}
1686
1687//----------------------------------------------------------------------------------------------------
1693{
1694 // check if any editor tab is present, if not: get out of here
1695 if ( !currentEditor() )
1696 return;
1697
1698 // check if there are any unsaved tabs
1699 for (int i=0; i<fTabWidget->count(); i++) {
1700 if (fTabWidget->tabText(i).indexOf("*") > 0) {
1701 int result = QMessageBox::warning(this, "WARNING",
1702 "Do you really want to close all files.\nChanges of unsaved files will be lost",
1703 QMessageBox::Close, QMessageBox::Cancel);
1704 if (result == QMessageBox::Cancel)
1705 return;
1706 break;
1707 }
1708 }
1709
1710 // close all editor tabs
1711 QString str;
1712 do {
1713 // remove file from file system watcher
1714 str = *fFilenames.find(currentEditor());
1715 fFileSystemWatcher->removePath(str);
1716
1717 delete currentEditor();
1718
1719 if ( currentEditor() )
1720 currentEditor()->viewport()->setFocus();
1721 } while ( currentEditor() );
1722}
1723
1724//----------------------------------------------------------------------------------------------------
1730{
1731 // check if any editor tab is present, if not: get out of here
1732 if ( !currentEditor() )
1733 return;
1734
1735 // check if there are any unsaved tabs
1736 for (int i=0; i<fTabWidget->count(); i++) {
1737 if (fTabWidget->tabText(i).indexOf("*") > 0) {
1738 int result = QMessageBox::warning(this, "WARNING",
1739 "Do you really want to close all files.\nChanges of unsaved files will be lost",
1740 QMessageBox::Close, QMessageBox::Cancel);
1741 if (result == QMessageBox::Cancel)
1742 return;
1743 break;
1744 }
1745 }
1746
1747 // keep label of the current editor
1748 QString label = fTabWidget->tabText(fTabWidget->currentIndex());
1749
1750 // check if only the current editor is present. If yes: nothing to be done
1751 if (fTabWidget->count() == 1)
1752 return;
1753
1754 // close all editor tabs
1755 int i=0;
1756 QString str;
1757 do {
1758 if (fTabWidget->tabText(i) != label) {
1759 // remove file from file system watcher
1760 str = *fFilenames.find(dynamic_cast<PSubTextEdit*>(fTabWidget->widget(i)));
1761 fFileSystemWatcher->removePath(str);
1762
1763 delete fTabWidget->widget(i);
1764 } else {
1765 i++;
1766 }
1767 } while ( fTabWidget->count() > 1 );
1768
1769 currentEditor()->viewport()->setFocus();
1770}
1771
1772//----------------------------------------------------------------------------------------------------
1777{
1778 // check if there are still some modified files open
1779 for (int i=0; i < fTabWidget->count(); i++) {
1780 if (fTabWidget->tabText(i).indexOf("*") > 0) {
1781 int result = QMessageBox::warning(this, "WARNING",
1782 "Do you really want to exit from the applcation.\nChanges will be lost",
1783 QMessageBox::Close, QMessageBox::Cancel);
1784 if (result == QMessageBox::Cancel)
1785 return;
1786 break;
1787 }
1788 }
1789
1790 fAdmin->saveRecentFiles();
1791
1792 qApp->quit();
1793}
1794
1795//----------------------------------------------------------------------------------------------------
1800{
1801 if ( !currentEditor() )
1802 return;
1803 currentEditor()->undo();
1804}
1805
1806//----------------------------------------------------------------------------------------------------
1811{
1812 if ( !currentEditor() )
1813 return;
1814 currentEditor()->redo();
1815}
1816
1817//----------------------------------------------------------------------------------------------------
1822{
1823 if ( !currentEditor() )
1824 return;
1825 currentEditor()->selectAll();
1826}
1827
1828//----------------------------------------------------------------------------------------------------
1833{
1834 if ( !currentEditor() )
1835 return;
1836 currentEditor()->cut();
1837}
1838
1839//----------------------------------------------------------------------------------------------------
1844{
1845 if ( !currentEditor() )
1846 return;
1847 currentEditor()->copy();
1848}
1849
1850//----------------------------------------------------------------------------------------------------
1855{
1856 if ( !currentEditor() )
1857 return;
1858 currentEditor()->paste();
1859}
1860
1861//----------------------------------------------------------------------------------------------------
1866{
1867 if ( !currentEditor() )
1868 return;
1869
1870 // check if first time called, and if yes create find and replace data structure
1871 if (fFindReplaceData == nullptr) {
1873 fFindReplaceData->findText = QString("");
1874 fFindReplaceData->replaceText = QString("");
1875 fFindReplaceData->caseSensitive = true;
1876 fFindReplaceData->wholeWordsOnly = false;
1877 fFindReplaceData->fromCursor = true;
1878 fFindReplaceData->findBackwards = false;
1879 fFindReplaceData->selectedText = false;
1880 fFindReplaceData->promptOnReplace = true;
1881 }
1882
1883 if (fFindReplaceData == nullptr) {
1884 QMessageBox::critical(this, "ERROR", "Couldn't invoke find data structure, sorry :-(", QMessageBox::Ok, QMessageBox::NoButton);
1885 return;
1886 }
1887
1888 PFindDialog *dlg = new PFindDialog(fFindReplaceData, currentEditor()->textCursor().hasSelection());
1889 if (dlg == nullptr) {
1890 QMessageBox::critical(this, "ERROR", "Couldn't invoke find dialog, sorry :-(", QMessageBox::Ok, QMessageBox::NoButton);
1891 return;
1892 }
1893
1894 dlg->exec();
1895
1896 if (dlg->result() != QDialog::Accepted) {
1897 delete dlg;
1898 return;
1899 }
1900
1901 fFindReplaceData = dlg->getData();
1902
1903 delete dlg;
1904 dlg = nullptr;
1905
1906 // try to find the search text
1907 if (!fFindReplaceData->fromCursor)
1908 currentEditor()->textCursor().setPosition(0);
1909
1910 QTextDocument::FindFlags flags;
1911 if (fFindReplaceData->caseSensitive)
1912 flags |= QTextDocument::FindCaseSensitively;
1913 else if (fFindReplaceData->findBackwards)
1914 flags |= QTextDocument::FindBackward;
1915 else if (fFindReplaceData->wholeWordsOnly)
1916 flags |= QTextDocument::FindWholeWords;
1917
1918 currentEditor()->find(fFindReplaceData->findText, flags);
1919}
1920
1921//----------------------------------------------------------------------------------------------------
1926{
1927 QTextDocument::FindFlags flags;
1928 if (fFindReplaceData->caseSensitive)
1929 flags |= QTextDocument::FindCaseSensitively;
1930 else if (fFindReplaceData->wholeWordsOnly)
1931 flags |= QTextDocument::FindWholeWords;
1932
1933 currentEditor()->find(fFindReplaceData->findText, flags);
1934}
1935
1936//----------------------------------------------------------------------------------------------------
1941{
1942 QTextDocument::FindFlags flags;
1943 if (fFindReplaceData->caseSensitive)
1944 flags |= QTextDocument::FindCaseSensitively;
1945 else if (fFindReplaceData->wholeWordsOnly)
1946 flags |= QTextDocument::FindWholeWords;
1947
1948 flags |= QTextDocument::FindBackward;
1949
1950 currentEditor()->find(fFindReplaceData->findText, flags);
1951}
1952
1953//----------------------------------------------------------------------------------------------------
1958{
1959 if ( !currentEditor() )
1960 return;
1961
1962 // check if first time called, and if yes create find and replace data structure
1963 if (fFindReplaceData == nullptr) {
1965 fFindReplaceData->findText = QString("");
1966 fFindReplaceData->replaceText = QString("");
1967 fFindReplaceData->caseSensitive = true;
1968 fFindReplaceData->wholeWordsOnly = false;
1969 fFindReplaceData->fromCursor = true;
1970 fFindReplaceData->findBackwards = false;
1971 fFindReplaceData->selectedText = false;
1972 fFindReplaceData->promptOnReplace = true;
1973 }
1974
1975 if (fFindReplaceData == nullptr) {
1976 QMessageBox::critical(this, "ERROR", "Couldn't invoke find&replace data structure, sorry :-(", QMessageBox::Ok, QMessageBox::NoButton);
1977 return;
1978 }
1979
1980 PReplaceDialog *dlg = new PReplaceDialog(fFindReplaceData, currentEditor()->textCursor().hasSelection());
1981 if (dlg == nullptr) {
1982 QMessageBox::critical(this, "ERROR", "Couldn't invoke find&replace dialog, sorry :-(", QMessageBox::Ok, QMessageBox::NoButton);
1983 return;
1984 }
1985
1986 dlg->exec();
1987
1988 if (dlg->result() != QDialog::Accepted) {
1989 delete dlg;
1990 return;
1991 }
1992
1993 fFindReplaceData = dlg->getData();
1994
1995 delete dlg;
1996 dlg = nullptr;
1997
1998 if (fFindReplaceData->promptOnReplace) {
1999 editFindNext();
2000
2001 PReplaceConfirmationDialog confirmDlg(this);
2002
2003 // connect all the necessary signals/slots
2004 QObject::connect(confirmDlg.fReplace_pushButton, SIGNAL(clicked()), this, SLOT(replace()));
2005 QObject::connect(confirmDlg.fReplaceAndClose_pushButton, SIGNAL(clicked()), this, SLOT(replaceAndClose()));
2006 QObject::connect(confirmDlg.fReplaceAll_pushButton, SIGNAL(clicked()), this, SLOT(replaceAll()));
2007 QObject::connect(confirmDlg.fFindNext_pushButton, SIGNAL(clicked()), this, SLOT(editFindNext()));
2008 QObject::connect(this, SIGNAL(close()), &confirmDlg, SLOT(accept()));
2009
2010 confirmDlg.exec();
2011 } else {
2012 replaceAll();
2013 }
2014}
2015
2016//----------------------------------------------------------------------------------------------------
2022{
2023 if ( !currentEditor() )
2024 return;
2025
2026
2027 QTextCursor curs = currentEditor()->textCursor();
2028
2029 if (curs.hasComplexSelection()) { // multiple selections
2030 // multiple selections (STILL MISSING)
2031 } else if (curs.hasSelection()) { // simple selection
2032 int pos = curs.position();
2033 int secStart = curs.selectionStart(); // keep start position of the selection
2034 int secEnd = curs.selectionEnd(); // keep end position of the selection
2035 curs.clearSelection();
2036 curs.setPosition(secStart); // set the anchor to the start of the selection
2037 curs.movePosition(QTextCursor::StartOfBlock);
2038 do {
2039 curs.insertText("#");
2040 } while (curs.movePosition(QTextCursor::NextBlock) && (curs.position() <= secEnd));
2041 curs.setPosition(pos+1);
2042 } else { // no selection
2043 int pos = curs.position();
2044 curs.clearSelection();
2045 curs.movePosition(QTextCursor::StartOfLine);
2046 curs.insertText("#");
2047 curs.setPosition(pos+1);
2048 }
2049}
2050
2051//----------------------------------------------------------------------------------------------------
2057{
2058 if ( !currentEditor() )
2059 return;
2060
2061
2062 QTextCursor curs = currentEditor()->textCursor();
2063
2064 if (curs.hasComplexSelection()) {
2065 // multiple selections (STILL MISSING)
2066 } else if (curs.hasSelection()) {
2067 int pos = curs.position();
2068 int secStart = curs.selectionStart(); // keep start position of the selection
2069 int secEnd = curs.selectionEnd(); // keep end position of the selection
2070 curs.clearSelection();
2071 curs.setPosition(secStart); // set the anchor to the start of the selection
2072 curs.movePosition(QTextCursor::StartOfBlock);
2073 while (curs.position() < secEnd) {
2074 QString line = curs.block().text();
2075 if (line.startsWith("#")) {
2076 line.remove(0, 1);
2077 curs.select(QTextCursor::BlockUnderCursor);
2078 curs.removeSelectedText();
2079 curs.insertText("\n"+line);
2080 pos -= 1;
2081 }
2082 curs.movePosition(QTextCursor::NextBlock);
2083 }
2084 curs.setPosition(pos);
2085 currentEditor()->setTextCursor(curs); // needed to update document cursor
2086 } else { // no selection
2087 int pos = curs.position();
2088 curs.clearSelection();
2089 curs.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor, 1);
2090 QString line = curs.block().text();
2091 if (line.startsWith("#")) {
2092 line.remove(0, 1);
2093 curs.select(QTextCursor::BlockUnderCursor);
2094 curs.removeSelectedText();
2095 if (currentEditor()->textCursor().columnNumber() == 0)
2096 curs.insertText(line);
2097 else
2098 curs.insertText("\n"+line);
2099 pos -= 1;
2100 }
2101 curs.setPosition(pos);
2102 currentEditor()->setTextCursor(curs); // needed to update document cursor
2103 }
2104}
2105
2106//----------------------------------------------------------------------------------------------------
2112void PTextEdit::textFamily( const QString &f )
2113{
2114 fAdmin->setFontName(f);
2115
2116 if ( currentEditor() == nullptr )
2117 return;
2118
2119 currentEditor()->setFont(QFont(f,fAdmin->getFontSize()));
2120 currentEditor()->viewport()->setFocus();
2121}
2122
2123//----------------------------------------------------------------------------------------------------
2129void PTextEdit::textSize( const QString &p )
2130{
2131 fAdmin->setFontSize(p.toInt());
2132
2133 if ( currentEditor() == nullptr)
2134 return;
2135
2136 currentEditor()->setFont(QFont(fAdmin->getFontName(), p.toInt()));
2137 currentEditor()->viewport()->setFocus();
2138}
2139
2140//----------------------------------------------------------------------------------------------------
2145{
2146 QString cmd = fAdmin->getExecPath() + "/musrWiz";
2147#if defined(Q_OS_DARWIN)
2148 cmd = QString("/Applications/musrWiz.app/Contents/MacOS/musrWiz");
2149#endif
2150 QString workDir = "./"; // think about it!!
2151 QStringList arg;
2152 arg << "--log";
2153
2154 QProcess *proc = new QProcess(this);
2155 if (proc == nullptr) {
2156 QMessageBox::critical(nullptr, "ERROR", "Couldn't invoke QProcess!");
2157 return;
2158 }
2159
2160 // handle return status of musrWiz
2161 connect(proc, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
2162 [=, this](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrWiz(exitCode, exitStatus); });
2163
2164 // make sure that the system environment variables are properly set
2165 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2166#if defined(Q_OS_DARWIN)
2167 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
2168#else
2169 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
2170#endif
2171 proc->setProcessEnvironment(env);
2172 proc->setWorkingDirectory(workDir);
2173 proc->start(cmd, arg);
2174 if (!proc->waitForStarted()) {
2175 // error handling
2176 QString msg(tr("Could not execute the output command: ")+cmd[0]);
2177 QMessageBox::critical( nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close );
2178 return;
2179 }
2180}
2181
2182//----------------------------------------------------------------------------------------------------
2187{
2188 if ( !currentEditor() )
2189 return;
2190
2191 int result = 0;
2192 int fittype = currentEditor()->getFitType();
2193 if (fAdmin->getEstimateN0Flag() && ((fittype==0) || (fittype==4)))
2194 result = QMessageBox::question(this, "Estimate N0 active",
2195 "Do you wish a chisq/mlh evaluation with an automatic N0 estimate?");
2196
2197 QString tabLabel = fTabWidget->tabText(fTabWidget->currentIndex());
2198 if (tabLabel == "noname") {
2199 QMessageBox::critical(this, "ERROR", "For a fit a real msr-file is needed.");
2200 return;
2201 } else if (tabLabel == "noname*") {
2202 fileSaveAs();
2203 } else if (tabLabel.indexOf("*") > 0) {
2204 fileSave();
2205 }
2206
2207 QVector<QString> cmd;
2208 QString str;
2209 str = fAdmin->getExecPath() + "/musrfit";
2210
2211 cmd.append(str);
2212 cmd.append(QFileInfo(*fFilenames.find( currentEditor())).fileName() );
2213 cmd.append("--chisq-only");
2214 if (fAdmin->getEstimateN0Flag() && (result == QMessageBox::Yes) && ((fittype==0) || (fittype==4)))
2215 cmd.append("--estimateN0");
2216 PFitOutputHandler fitOutputHandler(QFileInfo(*fFilenames.find( currentEditor() )).absolutePath(), cmd);
2217 fitOutputHandler.setModal(true);
2218 fitOutputHandler.exec();
2219}
2220
2221//----------------------------------------------------------------------------------------------------
2226{
2227 if ( !currentEditor() )
2228 return;
2229
2230 QString tabLabel = fTabWidget->tabText(fTabWidget->currentIndex());
2231 if (tabLabel == "noname") {
2232 QMessageBox::critical(this, "ERROR", "For a fit a real msr-file is needed.");
2233 return;
2234 } else if (tabLabel == "noname*") {
2235 fileSaveAs();
2236 } else if (tabLabel.indexOf("*") > 0) {
2237 fileSave();
2238 }
2239
2240 QVector<QString> cmd;
2241 QString str;
2242 str = fAdmin->getExecPath() + "/musrfit";
2243
2244 cmd.append(str);
2245 cmd.append(QFileInfo(*fFilenames.find( currentEditor())).fileName() );
2246
2247 // check if keep minuit2 output is wished
2248 if (fAdmin->getKeepMinuit2OutputFlag())
2249 cmd.append("--keep-mn2-output");
2250
2251 // check if title of the data file should be used to replace the msr-file title
2252 if (fAdmin->getTitleFromDataFileFlag())
2253 cmd.append("--title-from-data-file");
2254
2255 // check if dump files are wished
2256 if (fAdmin->getDumpAsciiFlag()) {
2257 cmd.append("--dump");
2258 cmd.append("ascii");
2259 }
2260 if (fAdmin->getDumpRootFlag()) {
2261 cmd.append("--dump");
2262 cmd.append("root");
2263 }
2264
2265 // check estimate N0 flag
2266 if (fAdmin->getEstimateN0Flag()) {
2267 cmd.append("--estimateN0");
2268 }
2269
2270 // check yamlOut flag
2271 if (fAdmin->getYamlOutFlag()) {
2272 cmd.append("--yaml");
2273 }
2274
2275 // check how many threads to be used
2276 cmd.append("--use-no-of-threads");
2277 QString noThreads = QString("%1").arg(fAdmin->getNoOfThreadsToBeUsed());
2278 cmd.append(noThreads);
2279
2280 // check per-run-block-chisq flag
2281 if (fAdmin->getChisqPerRunBlockFlag()) {
2282 cmd.append("--per-run-block-chisq");
2283 }
2284
2285 // add timeout
2286 cmd.append("--timeout");
2287 QString numStr;
2288 numStr.setNum(fAdmin->getTimeout());
2289 cmd.append(numStr);
2290
2291 PFitOutputHandler fitOutputHandler(QFileInfo(*fFilenames.find( currentEditor() )).absolutePath(), cmd);
2292 fitOutputHandler.setModal(true);
2294 fitOutputHandler.exec();
2295
2296 // handle the reloading of the files
2297
2298 // get current file name
2299 QString currentFileName = *fFilenames.find( currentEditor() );
2300 QString complementFileName;
2301 // check if it is a msr-, mlog-, or another file
2302 int idx;
2303 if ((idx = currentFileName.indexOf(".msr")) > 0) { // msr-file
2304 complementFileName = currentFileName;
2305 complementFileName.replace(idx, 5, ".mlog");
2306 } else if ((idx = currentFileName.indexOf(".mlog")) > 0) { // mlog-file
2307 complementFileName = currentFileName;
2308 complementFileName.replace(idx, 5, ".msr ");
2309 complementFileName = complementFileName.trimmed();
2310 } else { // neither a msr- nor a mlog-file
2311 QMessageBox::information( this, "musrFit",
2312 "This is neither a msr- nor a mlog-file, hence no idea what to be done.\n",
2313 QMessageBox::Ok );
2314 return;
2315 }
2316
2317 int currentIdx = fTabWidget->currentIndex();
2318
2319 // reload current file
2320 fileClose();
2321 load(currentFileName, currentIdx);
2322
2323 // check if swap file is open as well, and if yes, reload it
2324 idx = -1;
2325 for (int i=0; i<fTabWidget->count(); i++) {
2326 if (fTabWidget->tabText(i).indexOf(complementFileName) >= 0) {
2327 idx = i;
2328 break;
2329 }
2330 }
2331 if (idx >= 0) { // complement file is open
2332 fTabWidget->setCurrentIndex(idx);
2333 fileClose();
2334 load(complementFileName, idx);
2335 fTabWidget->setCurrentIndex(currentIdx);
2336 }
2337
2339}
2340
2341//----------------------------------------------------------------------------------------------------
2346{
2347 if (fMsr2DataParam == nullptr) {
2349 *fMsr2DataParam = fAdmin->getMsr2DataParam();
2350 }
2351
2352 // init fMsr2DataParam
2353 fMsr2DataParam->keepMinuit2Output = fAdmin->getKeepMinuit2OutputFlag();
2354 fMsr2DataParam->titleFromDataFile = fAdmin->getTitleFromDataFileFlag();
2355 fMsr2DataParam->estimateN0 = fAdmin->getEstimateN0Flag();
2356 fMsr2DataParam->yamlOut = fAdmin->getYamlOutFlag();
2357 fMsr2DataParam->perRunBlockChisq = fAdmin->getChisqPerRunBlockFlag();
2358
2359 PMsr2DataDialog *dlg = new PMsr2DataDialog(fMsr2DataParam, fAdmin->getHelpUrl("msr2data"));
2360
2361 if (dlg == nullptr) {
2362 QMessageBox::critical(this, "ERROR", "Couldn't invoke msr2data dialog, sorry :-(", QMessageBox::Ok, QMessageBox::NoButton);
2363 return;
2364 }
2365
2366 if (dlg->exec() == QDialog::Accepted) {
2367 QString runList;
2368 QString runListFileName;
2369 QFileInfo fi;
2370 QString str;
2371 int i, end;
2372 QStringList list;
2373 bool ok;
2374
2376 fAdmin->setKeepMinuit2OutputFlag(fMsr2DataParam->keepMinuit2Output);
2377 fAdmin->setTitleFromDataFileFlag(fMsr2DataParam->titleFromDataFile);
2378 fAdmin->setEstimateN0Flag(fMsr2DataParam->estimateN0);
2379 fAdmin->setYamlOutFlag(fMsr2DataParam->yamlOut);
2380 fAdmin->setChisqPerRunBlockFlag(fMsr2DataParam->perRunBlockChisq);
2381
2382 // analyze parameters
2383 switch (dlg->getRunTag()) {
2384 case -1: // not valid
2385 QMessageBox::critical(this, "ERROR",
2386 "No valid run list input found :-(\nCannot do anything.",
2387 QMessageBox::Ok, QMessageBox::NoButton);
2388 return;
2389 break;
2390 case 0: // run list
2391 runList = fMsr2DataParam->runList;
2392 break;
2393 case 1: // run list file name
2394 runListFileName = fMsr2DataParam->runListFileName;
2395 fi.setFile(QFileInfo(*fFilenames.find( currentEditor() )).absolutePath() + "/" + runListFileName);
2396 if (!fi.exists()) {
2397 str = QString("Run List File '%1' doesn't exist.").arg(runListFileName);
2398 QMessageBox::critical(this, "ERROR",
2399 str, QMessageBox::Ok, QMessageBox::NoButton);
2400 return;
2401 }
2402 break;
2403 default: // never should reach this point
2404 QMessageBox::critical(this, "ERROR",
2405 "No idea how you could reach this point.\nPlease contact the developers.",
2406 QMessageBox::Ok, QMessageBox::NoButton);
2407 return;
2408 break;
2409 }
2410
2411 // form command
2412 QVector<QString> cmd;
2413
2414 str = fAdmin->getExecPath() + "/msr2data";
2415 cmd.append(str);
2416
2417 // run list argument
2418 switch (dlg->getRunTag()) {
2419 case 0:
2420 end = 0;
2421 while (!runList.section(' ', end, end, QString::SectionSkipEmpty).isEmpty()) {
2422 end++;
2423 }
2424 // first element
2425 if (end == 1) {
2426 str = "[" + runList + "]";
2427 cmd.append(str);
2428 } else {
2429 str = "[" + runList.section(' ', 0, 0, QString::SectionSkipEmpty);
2430 cmd.append(str);
2431 // middle elements
2432 for (i=1; i<end-1; i++) {
2433 cmd.append(runList.section(' ', i, i, QString::SectionSkipEmpty));
2434 }
2435 // last element
2436 str = runList.section(' ', end-1, end-1, QString::SectionSkipEmpty) + "]";
2437 cmd.append(str);
2438 }
2439 break;
2440 case 1:
2441 cmd.append(runListFileName);
2442 break;
2443 default:
2444 break;
2445 }
2446
2447 // file extension
2448 str = fMsr2DataParam->msrFileExtension;
2449 if (str.isEmpty())
2450 cmd.append("");
2451 else
2452 cmd.append(str);
2453
2454 // options
2455
2456 // parameter export list
2457 if (!fMsr2DataParam->paramList.isEmpty()) {
2458 cmd.append("paramList");
2459 QStringList list = fMsr2DataParam->paramList.split(QRegularExpression("[(\\s|,|;)]"), Qt::SkipEmptyParts);
2460 for (int i=0; i<list.size(); i++)
2461 cmd.append(list[i]);
2462 }
2463
2464 // no header flag?
2465 if (!fMsr2DataParam->writeDbHeader)
2466 cmd.append("noheader");
2467
2468 // ignore data header info flag present?
2469 if (fMsr2DataParam->ignoreDataHeaderInfo)
2470 cmd.append("nosummary");
2471
2472 // template run no fitting but: (i) no fit only flag, (ii) no create msr-file only flag
2473 if ((fMsr2DataParam->templateRunNo != -1) && !fMsr2DataParam->fitOnly && !fMsr2DataParam->createMsrFileOnly) {
2474 str = QString("%1").arg(fMsr2DataParam->templateRunNo);
2475 str = "fit-" + str;
2476 if (!fMsr2DataParam->chainFit) {
2477 str += "!";
2478 }
2479 cmd.append(str);
2480 }
2481
2482 // template run no AND create msr-file only flag
2483 if ((fMsr2DataParam->templateRunNo != -1) && fMsr2DataParam->createMsrFileOnly) {
2484 str = QString("%1").arg(fMsr2DataParam->templateRunNo);
2485 str = "msr-" + str;
2486 cmd.append(str);
2487 }
2488
2489 // fit only
2490 if (fMsr2DataParam->fitOnly) {
2491 str = "fit";
2492 cmd.append(str);
2493 }
2494
2495 // keep minuit2 output
2496 if (fMsr2DataParam->keepMinuit2Output) {
2497 cmd.append("-k");
2498 }
2499
2500 // replace msr-file title by data file title. Add flag only if a fit is done
2501 if (fMsr2DataParam->titleFromDataFile && (fMsr2DataParam->fitOnly || fMsr2DataParam->templateRunNo != -1)) {
2502 cmd.append("-t");
2503 }
2504
2505 // estimate N0 (makes sence for single histo and muMinus fits only). Add flag only if a fit is done
2506 if (fMsr2DataParam->estimateN0 && (fMsr2DataParam->fitOnly || fMsr2DataParam->templateRunNo != -1)) {
2507 cmd.append("-e");
2508 }
2509
2510 // yaml out. Add flag only if a fit is done
2511 if (fMsr2DataParam->yamlOut && (fMsr2DataParam->fitOnly || fMsr2DataParam->templateRunNo != -1)) {
2512 cmd.append("-y");
2513 }
2514
2515 // write per-run-block chisq. Add flag only if a fit is done
2516 if (fMsr2DataParam->perRunBlockChisq && (fMsr2DataParam->fitOnly || fMsr2DataParam->templateRunNo != -1)) {
2517 cmd.append("-p");
2518 }
2519
2520 // DB output wished
2521 if (!fMsr2DataParam->dbOutputFileName.isEmpty()) {
2522 str = "-o" + fMsr2DataParam->dbOutputFileName;
2523 cmd.append(str);
2524 }
2525
2526 // write column data
2527 if (fMsr2DataParam->writeColumnData) {
2528 cmd.append("data");
2529 }
2530
2531 // global flag check
2532 if (fMsr2DataParam->global) {
2533 cmd.append("global");
2534 }
2535
2536 // global+ flag check
2537 if (fMsr2DataParam->globalPlus) {
2538 if (fMsr2DataParam->chainFit) {
2539 cmd.append("global+");
2540 } else {
2541 cmd.append("global+!");
2542 }
2543 }
2544
2545 // recreate db file
2546 if (fMsr2DataParam->recreateDbFile) {
2547 cmd.append("new");
2548 }
2549
2550 // if NO tab is present use the local directory
2551 QString workDir = QString("./");
2552 if (fTabWidget->count() != 0) {
2553 workDir = QFileInfo(*fFilenames.find( currentEditor() )).absolutePath();
2554 }
2555 PFitOutputHandler fitOutputHandler(workDir, cmd);
2556 fitOutputHandler.setModal(true);
2558 fitOutputHandler.exec();
2559
2560 // check if it is necessary to load msr-files
2561 if (fMsr2DataParam->openFilesAfterFitting) {
2562 QString fln;
2563 QFile *file;
2564 QTextStream *stream;
2565 QFileInfo finfo;
2566 bool alreadOpen=false;
2567 int idx=0;
2568
2569 if (!fMsr2DataParam->global) { // standard fits
2570 switch(dlg->getRunTag()) {
2571 case 0: // run list
2572 list = getRunList(runList, ok);
2573 if (!ok)
2574 return;
2575 for (int i=0; i<list.size(); i++) {
2576 fln = list[i];
2577 if (fMsr2DataParam->msrFileExtension.isEmpty())
2578 fln += ".msr";
2579 else
2580 fln += fMsr2DataParam->msrFileExtension + ".msr";
2581
2582 workDir = QString("./");
2583 if (fTabWidget->count() != 0) {
2584 workDir = QFileInfo(*fFilenames.find( currentEditor() )).absolutePath();
2585 }
2586 finfo.setFile(workDir + "/" + fln);
2587 alreadOpen = fileAlreadyOpen(finfo, idx);
2588 if (!alreadOpen) {
2589 load(workDir + "/" + fln);
2590 } else {
2591 fTabWidget->setCurrentIndex(idx);
2592 fileReload();
2593 }
2594 }
2595 break;
2596 case 1: // run list file
2597 file = new QFile(QFileInfo(*fFilenames.find( currentEditor() )).absolutePath() + "/" + fMsr2DataParam->runListFileName);
2598 if (!file->open(QIODevice::ReadOnly)) {
2599 str = QString("Couldn't open run list file %1, sorry.").arg(fMsr2DataParam->runListFileName);
2600 QMessageBox::critical(this, "ERROR", str.toLatin1(), QMessageBox::Ok, QMessageBox::NoButton);
2601 return;
2602 }
2603
2604 stream = new QTextStream(file);
2605 while ( !stream->atEnd() ) {
2606 str = stream->readLine(); // line of text excluding '\n'
2607 str = str.trimmed();
2608 if (!str.isEmpty() && !str.startsWith("#") && !str.startsWith("run", Qt::CaseInsensitive)) {
2609 fln = str.section(' ', 0, 0, QString::SectionSkipEmpty);
2610 if (fMsr2DataParam->msrFileExtension.isEmpty())
2611 fln += ".msr";
2612 else
2613 fln += fMsr2DataParam->msrFileExtension + ".msr";
2614
2615 workDir = QString("./");
2616 if (fTabWidget->count() != 0) {
2617 workDir = QFileInfo(*fFilenames.find( currentEditor() )).absolutePath();
2618 }
2619 finfo.setFile(workDir + "/" + fln);
2620 alreadOpen = fileAlreadyOpen(finfo, idx);
2621 if (!alreadOpen) {
2622 load(workDir + "/" + fln);
2623 } else {
2624 fTabWidget->setCurrentIndex(idx);
2625 fileReload();
2626 }
2627 }
2628 }
2629
2630 file->close();
2631
2632 // clean up
2633 delete stream;
2634 delete file;
2635 break;
2636 default:
2637 break;
2638 }
2639 } else { // global tag set
2640 // get the first run number needed to build the global fit file name
2641 fln = QString("");
2642 switch(dlg->getRunTag()) {
2643 case 0: // run list
2644 fln = runList.section(" ", 0, 0, QString::SectionSkipEmpty) + QString("+global") + fMsr2DataParam->msrFileExtension + QString(".msr");
2645 break;
2646 case 1: // run list file name
2647 file = new QFile(QFileInfo(*fFilenames.find( currentEditor() )).absolutePath() + "/" + fMsr2DataParam->runListFileName);
2648 if (!file->open(QIODevice::ReadOnly)) {
2649 str = QString("Couldn't open run list file %1, sorry.").arg(fMsr2DataParam->runListFileName);
2650 QMessageBox::critical(this, "ERROR", str.toLatin1(), QMessageBox::Ok, QMessageBox::NoButton);
2651 return;
2652 }
2653
2654 stream = new QTextStream(file);
2655 while ( !stream->atEnd() ) {
2656 str = stream->readLine(); // line of text excluding '\n'
2657 str = str.trimmed();
2658 if (!str.isEmpty() && !str.startsWith("#") && !str.startsWith("run", Qt::CaseInsensitive)) {
2659 fln = str.section(' ', 0, 0, QString::SectionSkipEmpty);
2660 break;
2661 }
2662 }
2663
2664 file->close();
2665
2666 fln += QString("+global") + fMsr2DataParam->msrFileExtension + QString(".msr");
2667
2668 // clean up
2669 delete stream;
2670 delete file;
2671 break;
2672 default:
2673 break;
2674 }
2675
2676 load(QFileInfo(*fFilenames.find( currentEditor() )).absolutePath() + "/" + fln);
2677 }
2678 }
2679 }
2680
2681 delete dlg;
2682 dlg = nullptr;
2683
2685}
2686
2687//----------------------------------------------------------------------------------------------------
2692{
2693 if ( !currentEditor() )
2694 return;
2695
2696 QString tabLabel = fTabWidget->tabText(fTabWidget->currentIndex());
2697 if (tabLabel == "noname") {
2698 QMessageBox::critical(this, "ERROR", "For a view a real mlog/msr-file is needed.");
2699 return;
2700 } else if (tabLabel == "noname*") {
2701 fileSaveAs();
2702 } else if (tabLabel.indexOf("*") > 0) {
2703 fileSave();
2704 }
2705
2706 QString cmd = fAdmin->getExecPath() + "/musrview";
2707 QString fln="./";
2709 if (ce != nullptr)
2710 fln = *fFilenames.find(currentEditor());
2711 QString workDir = QFileInfo(fln).absolutePath();
2712 QStringList arg;
2713 QString str;
2714
2715 // file name
2716 str = fln;
2717 int pos = str.lastIndexOf("/");
2718 if (pos != -1)
2719 str.remove(0, pos+1);
2720 arg << str;
2721
2722 // timeout
2723 str.setNum(fAdmin->getTimeout());
2724 arg << "--timeout" << str;
2725
2726 // start with Fourier?
2727 if (fAdmin->getMusrviewShowFourierFlag())
2728 arg << "-f";
2729
2730 // start with averaged data/Fourier?
2731 if (fAdmin->getMusrviewShowAvgFlag())
2732 arg << "-a";
2733
2734 // check if theory shall only be calculated at the data points
2735 if (fAdmin->getMusrviewShowOneToOneFlag())
2736 arg << "-1";
2737
2738 // add error message box option
2739 arg << "-s";
2740
2741 QProcess proc;
2742 // make sure that the system environment variables are properly set
2743 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2744#if defined(Q_OS_DARWIN)
2745 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
2746#else
2747 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
2748#endif
2749 proc.setProgram(cmd);
2750 proc.setProcessEnvironment(env);
2751 proc.setArguments(arg);
2752 proc.setWorkingDirectory(workDir);
2753 if (!proc.startDetached()) {
2754 QString msg = QString("musrview failed. Possible reasons:\n");
2755 msg += QString("* corrupted msr-file.\n");
2756 msg += QString("* cannot read data-file.\n");
2757 msg += QString("* many more things can go wrong.\n");
2758 msg += QString("Please check!");
2759 QMessageBox::critical(nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close);
2760 }
2761}
2762
2763//----------------------------------------------------------------------------------------------------
2768{
2769 QStringList flns = QFileDialog::getOpenFileNames( this, tr("Open msr-/mlog-File"),
2771 tr( "msr-Files (*.msr)" ));
2772 if (flns.isEmpty())
2773 return;
2774
2775 QString cmd = fAdmin->getExecPath() + "/musrview";
2776 QString fln="./";
2778 if (ce != nullptr)
2779 fln = *fFilenames.find(currentEditor());
2780 QString workDir = QFileInfo(fln).absolutePath();
2781 QStringList arg;
2782
2783 for (auto it : flns) {
2784 std::cout << it.toLatin1().data() << std::endl;
2785 arg.clear();
2786 arg << it;
2787
2788 // start with Fourier?
2789 if (fAdmin->getMusrviewShowFourierFlag())
2790 arg << "-f";
2791
2792 // start with averaged data/Fourier?
2793 if (fAdmin->getMusrviewShowAvgFlag())
2794 arg << "-a";
2795
2796 // check if theory shall only be calculated at the data points
2797 if (fAdmin->getMusrviewShowOneToOneFlag())
2798 arg << "-1";
2799
2800 arg << "--ascii";
2801
2802 QProcess proc;
2803 // make sure that the system environment variables are properly set
2804 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2805#if defined(Q_OS_DARWIN)
2806 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
2807#else
2808 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
2809#endif
2810 proc.setProgram(cmd);
2811 proc.setProcessEnvironment(env);
2812 proc.setArguments(arg);
2813 proc.setWorkingDirectory(workDir);
2814 if (!proc.startDetached()) {
2815 QString msg = QString("musrview failed. Possible reasons:\n");
2816 msg += QString("* corrupted msr-file.\n");
2817 msg += QString("* cannot read data-file.\n");
2818 msg += QString("* many more things can go wrong.\n");
2819 msg += QString("Please check!");
2820 QMessageBox::critical(nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close);
2821 }
2822 }
2823
2824 QMessageBox::information(this, "INFO", "<b>In the pipeline</b>.\nIt might take a couple of seconds to complete everything.");
2825}
2826
2827//----------------------------------------------------------------------------------------------------
2832{
2833 if ( !currentEditor() )
2834 return;
2835
2836 QString tabLabel = fTabWidget->tabText(fTabWidget->currentIndex());
2837 if (tabLabel == "noname") {
2838 QMessageBox::critical(this, "ERROR", "For a view a real mlog/msr-file is needed.");
2839 return;
2840 } else if (tabLabel == "noname*") {
2841 fileSaveAs();
2842 } else if (tabLabel.indexOf("*") > 0) {
2843 fileSave();
2844 }
2845
2846 QString cmd = fAdmin->getExecPath() + "/musrt0";
2847 QString workDir = QFileInfo(*fFilenames.find(currentEditor())).absolutePath();
2848 QStringList arg;
2849 QString str;
2850
2851 // file name
2852 str = *fFilenames.find(currentEditor());
2853 int pos = str.lastIndexOf("/");
2854 if (pos != -1)
2855 str.remove(0, pos+1);
2856 arg << str;
2857
2858 // timeout
2859 str.setNum(fAdmin->getTimeout());
2860 arg << "--timeout" << str;
2861
2862 QProcess *proc = new QProcess(this);
2863
2864 // make sure that the system environment variables are properly set
2865 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2866#if defined(Q_OS_DARWIN)
2867 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
2868#else
2869 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
2870#endif
2871 proc->setProcessEnvironment(env);
2872 proc->setWorkingDirectory(workDir);
2873
2874 connect(proc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
2875 [=, this](int exitCode, QProcess::ExitStatus exitStatus){ fileReload(); });
2876
2877 proc->start(cmd, arg);
2878 if (!proc->waitForStarted()) {
2879 // error handling
2880 QString msg(tr("Could not execute the output command: ")+cmd[0]);
2881 QMessageBox::critical( nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close );
2882 return;
2883 }
2884}
2885
2886//----------------------------------------------------------------------------------------------------
2892{
2894 if (ce == nullptr)
2895 return;
2896
2898
2899 if (dlg == nullptr) {
2900 QMessageBox::critical(this, "ERROR musrFT", "Couldn't invoke musrFT Options Dialog.");
2901 return;
2902 }
2903
2904 if (dlg->exec() == QDialog::Accepted) {
2906 QProcess *proc = new QProcess(this);
2907 proc->setStandardOutputFile("musrFT.log");
2908 proc->setStandardErrorFile("musrFT.log");
2909 QString cmd = fAdmin->getExecPath() + "/musrFT";
2910 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
2911#if defined(Q_OS_DARWIN)
2912 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
2913#else
2914 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
2915#endif
2916 proc->setProcessEnvironment(env);
2917 proc->start(cmd, fMusrFTPrevCmd);
2918 if (!proc->waitForStarted()) {
2919 // error handling
2920 QString msg(tr("Could not execute the output command: ")+cmd[0]);
2921 QMessageBox::critical( nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close );
2922 return;
2923 }
2924 }
2925
2926 delete dlg;
2927 dlg = nullptr;
2928}
2929
2930//----------------------------------------------------------------------------------------------------
2935{
2936 PPrefsDialog *dlg = new PPrefsDialog(fAdmin.get());
2937
2938 if (dlg == nullptr) {
2939 QMessageBox::critical(this, "ERROR musrPrefs", "Couldn't invoke Preferences Dialog.");
2940 return;
2941 }
2942
2943 if (dlg->exec() == QDialog::Accepted) {
2944 fAdmin->setIgnoreThemeAutoDetection(dlg->getIgnoreThemeAutoDetection());
2945 fAdmin->setDarkThemeIconsMenuFlag(dlg->getDarkThemeIconsMenuFlag());
2946 fAdmin->setDarkThemeIconsToolbarFlag(dlg->getDarkThemeIconsToolbarFlag());
2947 fAdmin->setMusrviewShowFourierFlag(dlg->getMusrviewShowFourierFlag());
2948 fAdmin->setMusrviewShowAvgFlag(dlg->getMusrviewShowAvgFlag());
2949 fAdmin->setMusrviewShowOneToOneFlag(dlg->getMusrviewShowOneToOneFlag());
2950 fAdmin->setKeepMinuit2OutputFlag(dlg->getKeepMinuit2OutputFlag());
2951 fAdmin->setTitleFromDataFileFlag(dlg->getTitleFromDataFileFlag());
2952 fAdmin->setEnableMusrT0Flag(dlg->getEnableMusrT0Flag());
2953 fMusrT0Action->setEnabled(fAdmin->getEnableMusrT0Flag());
2954 if (dlg->getDump() == 1) {
2955 fAdmin->setDumpAsciiFlag(true);
2956 fAdmin->setDumpRootFlag(false);
2957 } else if (dlg->getDump() == 2) {
2958 fAdmin->setDumpAsciiFlag(false);
2959 fAdmin->setDumpRootFlag(true);
2960 } else {
2961 fAdmin->setDumpAsciiFlag(false);
2962 fAdmin->setDumpRootFlag(false);
2963 }
2964 fAdmin->setTimeout(dlg->getTimeout());
2965 fAdmin->setChisqPerRunBlockFlag(dlg->getKeepRunPerBlockChisqFlag());
2966 fAdmin->setEstimateN0Flag(dlg->getEstimateN0Flag());
2967 fAdmin->setYamlOutFlag(dlg->getYamlOutFlag());
2968 }
2969
2970 delete dlg;
2971 dlg = nullptr;
2972
2973 // check if the dark theme menu icons flag has changed
2974 if (fAdmin->getDarkThemeIconsMenuFlag() != fDarkMenuIcon) {
2977 }
2978 // check if the dark theme toolbar icons flag has changed
2979 if (fAdmin->getDarkThemeIconsToolbarFlag() != fDarkToolBarIcon) {
2982 }
2983}
2984
2985//----------------------------------------------------------------------------------------------------
2990{
2991 if ( !currentEditor() )
2992 return;
2993
2994 // make sure I have a saved msr-file to work on
2995 QString tabLabel = fTabWidget->tabText(fTabWidget->currentIndex());
2996 if (tabLabel == "noname") {
2997 QMessageBox::critical(this, "ERROR", "For musrStep a real mlog/msr-file is needed.");
2998 return;
2999 } else if (tabLabel == "noname*") {
3000 fileSaveAs();
3001 } else if (tabLabel.indexOf("*") > 0) {
3002 fileSave();
3003 }
3004
3005 // fill the command queue
3006 QString cmd = fAdmin->getExecPath() + "/musrStep";
3007#if defined(Q_OS_DARWIN)
3008 cmd = QString("/Applications/musrStep.app/Contents/MacOS/musrStep");
3009#endif
3010 QString workDir = QFileInfo(*fFilenames.find(currentEditor())).absolutePath();
3011 QStringList arg;
3012 QString str;
3013
3014 // get file name and feed it to the command queue
3015 str = *fFilenames.find(currentEditor());
3016 int pos = str.lastIndexOf("/");
3017 if (pos != -1)
3018 str.remove(0, pos+1);
3019 arg << str;
3020
3021 QProcess *proc = new QProcess(this);
3022 if (proc == nullptr) {
3023 QMessageBox::critical(nullptr, "ERROR", "Couldn't invoke QProcess!");
3024 return;
3025 }
3026
3027 // handle return status of musrStep
3028 connect(proc, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
3029 [=, this](int exitCode, QProcess::ExitStatus exitStatus){ exitStatusMusrSetSteps(exitCode, exitStatus); });
3030
3031 // make sure that the system environment variables are properly set
3032 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
3033#if defined(Q_OS_DARWIN)
3034 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
3035#else
3036 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
3037#endif
3038 proc->setProcessEnvironment(env);
3039 proc->setWorkingDirectory(workDir);
3040 proc->start(cmd, arg);
3041 if (!proc->waitForStarted()) {
3042 // error handling
3043 QString msg(tr("Could not execute the output command: ")+cmd[0]);
3044 QMessageBox::critical( nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close );
3045 return;
3046 }
3047}
3048
3049//----------------------------------------------------------------------------------------------------
3054{
3055 if ( !currentEditor() )
3056 return;
3057
3058 // get current file name
3059 QString currentFileName = *fFilenames.find( currentEditor() );
3060 QString swapFileName;
3061 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
3062 QString tempFileName = QString("%1/.musrfit/__swap__.msr").arg(env.value("HOME"));
3063
3064 // check if it is a msr-, mlog-, or another file
3065 int idx;
3066 if ((idx = currentFileName.indexOf(".msr")) > 0) { // msr-file
3067 swapFileName = currentFileName;
3068 swapFileName.replace(idx, 5, ".mlog");
3069 } else if ((idx = currentFileName.indexOf(".mlog")) > 0) { // mlog-file
3070 swapFileName = currentFileName;
3071 swapFileName.replace(idx, 5, ".msr ");
3072 swapFileName = swapFileName.trimmed();
3073 } else { // neither a msr- nor a mlog-file
3074 QMessageBox::information( this, "musrSwapMsrMlog",
3075 "This is neither a msr- nor a mlog-file, hence nothing to be swapped.\n",
3076 QMessageBox::Ok );
3077 return;
3078 }
3079
3080 // check if the swapFile exists
3081 if (!QFile::exists(swapFileName)) {
3082 QString msg = "swap file '" + swapFileName + "' doesn't exist.\nCannot swap anything.";
3083 QMessageBox::warning( this, "musrSwapMsrMlog",
3084 msg, QMessageBox::Ok, QMessageBox::NoButton );
3085 return;
3086 }
3087
3088 if (QMessageBox::information(this, "INFO",
3089 QString("Will now swap files: %1 <-> %2").arg(currentFileName).arg(swapFileName),
3090 QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Cancel)
3091 return;
3092
3093 // check if the file needs to be saved
3094 if (fTabWidget->tabText(fTabWidget->currentIndex()).indexOf("*") > 0) { // needs to be saved first
3095 fileSave();
3096 }
3097
3098 // swap files
3099
3100 // copy currentFile -> tempFile
3101 if (QFile::exists(tempFileName)) {
3102 if (!QFile::remove(tempFileName)) {
3103 QMessageBox::critical(nullptr, "ERROR", QString("failed to remove %1").arg(tempFileName));
3104 return;
3105 }
3106 }
3107 if (!QFile::copy(currentFileName, tempFileName)) {
3108 QMessageBox::critical(nullptr, "ERROR", QString("failed to copy %1 -> %2").arg(currentFileName).arg(tempFileName));
3109 return;
3110 }
3111 // copy swapFile -> currentFile
3112 if (!QFile::remove(currentFileName)) {
3113 QMessageBox::critical(nullptr, "ERROR", QString("failed to remove %1").arg(currentFileName));
3114 return;
3115 }
3116 if (!QFile::copy(swapFileName, currentFileName)) {
3117 QMessageBox::critical(nullptr, "ERROR", QString("failed to copy %1 -> %2").arg(swapFileName).arg(currentFileName));
3118 return;
3119 }
3120 // copy tempFile -> swapFile
3121 if (!QFile::remove(swapFileName)) {
3122 QMessageBox::critical(nullptr, "ERROR", QString("failed to remove %1").arg(swapFileName));
3123 return;
3124 }
3125 if (!QFile::copy(tempFileName, swapFileName)) {
3126 QMessageBox::critical(nullptr, "ERROR", QString("failed to copy %1 -> %2").arg(tempFileName).arg(swapFileName));
3127 return;
3128 }
3129 // clean up
3130 if (!QFile::remove(tempFileName)) {
3131 QMessageBox::critical(nullptr, "ERROR", QString("failed to remove %1").arg(tempFileName));
3132 return;
3133 }
3134
3135 int currentIdx = fTabWidget->currentIndex();
3136
3137 // reload current file
3138 fileClose();
3139 load(currentFileName);
3140
3141 // check if swap file is open as well, and if yes, reload it
3142 idx = -1;
3143 for (int i=0; i<fTabWidget->count(); i++) {
3144 if (fTabWidget->tabText(i).indexOf(swapFileName) >= 0) {
3145 idx = i;
3146 break;
3147 }
3148 }
3149 if (idx >= 0) { // swap file is open
3150 fTabWidget->setCurrentIndex(idx);
3151 fileClose();
3152 load(swapFileName);
3153 fTabWidget->setCurrentIndex(currentIdx);
3154 }
3155}
3156
3157//----------------------------------------------------------------------------------------------------
3162{
3163 // select a muSR data filename
3164 QString fileName = QFileDialog::getOpenFileName(this, tr("Select muSR Data File"), "./", tr("muSR Data Files (*.root *.bin *.msr *.nxs)"));
3165 if (fileName.isEmpty())
3166 return;
3167
3168 QVector<QString> cmd;
3169 QString str = fAdmin->getExecPath() + "/dump_header";
3170 cmd.append(str);
3171 cmd.append("-fn");
3172 cmd.append(fileName);
3173 cmd.append("-c");
3174
3175 PDumpOutputHandler dumpOutputHandler(cmd);
3176 dumpOutputHandler.setModal(false);
3177 dumpOutputHandler.exec();
3178}
3179
3180//----------------------------------------------------------------------------------------------------
3186{
3187 QString cmd("");
3188 cmd = fAdmin->getExecPath() + "/mupp";
3189#if defined(Q_OS_DARWIN)
3190 cmd = QString("/Applications/mupp.app/Contents/MacOS/mupp");
3191#endif
3192
3193 QStringList arg;
3194
3195 QProcess *proc = new QProcess(this);
3196
3197 QString fln="./";
3199 if (ce != nullptr)
3200 fln = *fFilenames.find(currentEditor());
3201 QString workDir = QFileInfo(fln).absolutePath();
3202
3203 // make sure that the system environment variables are properly set
3204 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
3205#if defined(Q_OS_DARWIN)
3206 env.insert("DYLD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:/usr/local/lib:" + env.value("DYLD_LIBRARY_PATH"));
3207#else
3208 env.insert("LD_LIBRARY_PATH", env.value("ROOTSYS") + "/lib:" + env.value("LD_LIBRARY_PATH"));
3209#endif
3210 proc->setProcessEnvironment(env);
3211 proc->setWorkingDirectory(workDir);
3212 proc->start(cmd, arg);
3213 if (!proc->waitForStarted()) {
3214 // error handling
3215 QString msg(tr("Could not execute the output command: ")+cmd);
3216 QMessageBox::critical( nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close );
3217 return;
3218 }
3219}
3220
3221//----------------------------------------------------------------------------------------------------
3226{
3227 bool ok = QDesktopServices::openUrl(QUrl(fAdmin->getHelpUrl("main"), QUrl::TolerantMode));
3228 if (!ok) {
3229 QString msg = QString("<p>Sorry: Couldn't open default web-browser for the help.<br>Please try: <a href=\"%1\">musrfit docu</a> in your web-browser.").arg(fAdmin->getHelpUrl("main"));
3230 QMessageBox::critical( nullptr, tr("FATAL ERROR"), msg, QMessageBox::Close );
3231 }
3232}
3233
3234//----------------------------------------------------------------------------------------------------
3239{
3240 PMusrEditAbout *about = new PMusrEditAbout();
3241 about->show();
3242}
3243
3244//----------------------------------------------------------------------------------------------------
3249{
3250 QMessageBox::aboutQt(this);
3251}
3252
3253
3254//----------------------------------------------------------------------------------------------------
3260void PTextEdit::exitStatusMusrWiz(int exitCode, QProcess::ExitStatus exitStatus)
3261{
3262 if (exitStatus == QProcess::CrashExit) {
3263 QMessageBox::critical(nullptr, "FATAL ERROR", "musrWiz returned CrashExit.");
3264 return;
3265 }
3266
3267 // dialog finished with reject
3268 if (exitCode == 0)
3269 return;
3270
3271 // read .musrWiz.log
3272 QProcessEnvironment procEnv = QProcessEnvironment::systemEnvironment();
3273 QString pathName = procEnv.value("HOME", "");
3274 pathName += "/.musrfit/musredit/musrWiz.log";
3275 QString errMsg;
3276 std::ifstream fin(pathName.toLatin1().data(), std::ifstream::in);
3277 if (!fin.is_open()) {
3278 errMsg = QString("PTextEdit::exitStatusMusrWiz: couldn't read %1 file.").arg(pathName);
3279 QMessageBox::critical(nullptr, "ERROR", errMsg);
3280 return;
3281 }
3282 char line[128];
3283 bool musrT0tag = false;
3284 QString str, pathFileName("");
3285 while (fin.good()) {
3286 fin.getline(line, 128);
3287 str = line;
3288 if (str.startsWith("path-file-name:")) {
3289 pathFileName = str.mid(16);
3290 } else if (str.startsWith("musrt0-tag: yes")) {
3291 musrT0tag = true;
3292 }
3293 }
3294 fin.close();
3295
3296 load(pathFileName);
3297
3298 // in case there is a 1st empty tab "noname", remove it
3299 QString tabStr = fTabWidget->tabText(0);
3300 tabStr.remove('&'); // this is needed since the QTabWidget adds short-cut info as '&' to the tab name
3301 if (tabStr == "noname") { // has to be the first, otherwise do nothing
3302 fFileSystemWatcher->removePath("noname");
3303
3304 delete fTabWidget->widget(0);
3305 }
3306
3307 if (musrT0tag)
3308 musrT0();
3309
3310 // remove musrWiz.log file
3311 QFile logFile(pathName);
3312 if (!logFile.remove()) {
3313 errMsg = QString("PTextEdit::exitStatusMusrWiz: couldn't delete %1 file.").arg(pathName);
3314 QMessageBox::critical(nullptr, "ERROR", errMsg);
3315 }
3316}
3317
3318//----------------------------------------------------------------------------------------------------
3324void PTextEdit::exitStatusMusrSetSteps(int exitCode, QProcess::ExitStatus exitStatus)
3325{
3326 if (exitStatus == QProcess::CrashExit) {
3327 QMessageBox::critical(nullptr, "FATAL ERROR", "musrStep returned CrashExit.");
3328 return;
3329 }
3330
3331 // dialog finished with reject
3332 if (exitCode == 0)
3333 return;
3334
3335 // dialog finished with save and quite, i.e. accept, hence reload
3336 QString fln = *fFilenames.find( currentEditor() );
3337 int idx = fTabWidget->currentIndex();
3338
3339 fileClose();
3340 load(fln, idx);
3341}
3342
3343//----------------------------------------------------------------------------------------------------
3349void PTextEdit::fontChanged( const QFont &f )
3350{
3351 fFontChanging = true;
3352 fComboFont->lineEdit()->setText( f.family() );
3353 fComboSize->lineEdit()->setText( QString::number( f.pointSize() ) );
3354
3355 if (!currentEditor())
3356 return;
3357
3358 currentEditor()->setFont(f);
3359 currentEditor()->setWindowModified(false);
3360 currentEditor()->viewport()->setFocus();
3361 fFontChanging = false;
3362}
3363
3364//----------------------------------------------------------------------------------------------------
3371void PTextEdit::textChanged(const bool forced)
3372{
3373
3374 if (!currentEditor())
3375 return;
3376
3377 if (fFontChanging)
3378 return;
3379
3380 QString tabLabel = fTabWidget->tabText(fTabWidget->currentIndex());
3381
3382 if ((fTabWidget->tabText(fTabWidget->currentIndex()).indexOf("*") > 0) &&
3383 !currentEditor()->document()->isModified()) {
3384 tabLabel.truncate(tabLabel.length()-1);
3385 fTabWidget->setTabText(fTabWidget->currentIndex(), tabLabel);
3386 }
3387
3388 if ((fTabWidget->tabText(fTabWidget->currentIndex()).indexOf("*") < 0) &&
3389 currentEditor()->document()->isModified()) {
3390 fTabWidget->setTabText(fTabWidget->currentIndex(), tabLabel+"*");
3391 }
3392
3393 if ((fTabWidget->tabText(fTabWidget->currentIndex()).indexOf("*") < 0) &&
3394 forced)
3395 fTabWidget->setTabText(fTabWidget->currentIndex(), tabLabel+"*");
3396}
3397
3398//----------------------------------------------------------------------------------------------------
3404{
3405 QString str;
3406 int line=0, pos=0;
3407
3408 pos = currentEditor()->textCursor().columnNumber();
3409 line = currentEditor()->textCursor().blockNumber();
3410
3411 str = QString("cursor pos: %1, %2").arg(line+1).arg(pos+1);
3412 statusBar()->showMessage(str);
3413}
3414
3415//----------------------------------------------------------------------------------------------------
3420{
3421 currentEditor()->insertPlainText(fFindReplaceData->replaceText);
3422
3423 editFindNext();
3424}
3425
3426//----------------------------------------------------------------------------------------------------
3431{
3432 currentEditor()->insertPlainText(fFindReplaceData->replaceText);
3433
3434 emit close();
3435}
3436
3437//----------------------------------------------------------------------------------------------------
3442{
3443 // set the cursor to the start of the document
3444 currentEditor()->moveCursor(QTextCursor::Start);
3445
3446 // construct search flags
3447 QTextDocument::FindFlags flags;
3448 if (fFindReplaceData->caseSensitive)
3449 flags |= QTextDocument::FindCaseSensitively;
3450 else if (fFindReplaceData->findBackwards)
3451 flags |= QTextDocument::FindBackward;
3452 else if (fFindReplaceData->wholeWordsOnly)
3453 flags |= QTextDocument::FindWholeWords;
3454
3455 while (currentEditor()->find(fFindReplaceData->findText, flags)) {
3456 currentEditor()->insertPlainText(fFindReplaceData->replaceText);
3457 }
3458
3459 emit close();
3460}
3461
3462//----------------------------------------------------------------------------------------------------
3467{
3468 QFont font(fAdmin->getFontName(), fAdmin->getFontSize());
3469 fontChanged(font);
3470}
3471
3472//----------------------------------------------------------------------------------------------------
3478void PTextEdit::fileChanged(const QString &fileName)
3479{
3481 return;
3482
3484
3485 QString str = "File '" + fileName + "' changed on the system.\nDo you want to reload it?";
3486 int result = QMessageBox::question(this, "INFO", str, QMessageBox::Yes, QMessageBox::No);
3487 if (result == QMessageBox::Yes) {
3488 // find correct file
3489 int idx = -1;
3490 for (int i=0; i<fTabWidget->count(); i++) {
3491 if (fTabWidget->tabText(i) == QFileInfo(fileName).fileName()) {
3492 idx = i;
3493 break;
3494 }
3495 }
3496
3497 if (idx == -1) {
3499 return;
3500 }
3501
3502 // remove file from file system watcher
3503 fFileSystemWatcher->removePath(fileName);
3504
3505 // close tab
3506 fTabWidget->removeTab(idx);
3507 // load it
3508 load(fileName, idx);
3509 }
3510
3512}
3513
3514//----------------------------------------------------------------------------------------------------
3520{
3521 if (fFileSystemWatcherTimeout.isActive())
3522 return;
3523
3524 fFileSystemWatcherTimeout.singleShot(2000, this, SLOT(setFileSystemWatcherActive()));
3525}
3526
3527//----------------------------------------------------------------------------------------------------
3536
3537//----------------------------------------------------------------------------------------------------
3543{
3544 QString str = fJumpToBlock->itemText(idx);
3545
3546 QTextDocument::FindFlags flags= QTextDocument::FindCaseSensitively | QTextDocument::FindWholeWords;
3547
3548 bool found = currentEditor()->find(str, flags);
3549 if (found)
3550 return;
3551
3552 // set cursor to start
3553 currentEditor()->moveCursor(QTextCursor::Start);
3554 currentEditor()->find(str, flags);
3555}
3556
3557//----------------------------------------------------------------------------------------------------
3562{
3563 if (fAdmin->getIgnoreThemeAutoDetection())
3564 return false;
3565
3566 fDarkMenuIcon = false; // true if theme is dark
3567 fDarkToolBarIcon = false; // needed for ubuntu dark since there the menu icons are dark, however the toolbar icons are plain!
3568
3569 QString str = QIcon::themeName();
3570
3571 if (str.isEmpty()) { // this is ugly and eventually needs to be fixed in a more coherent way
3572 str = QProcessEnvironment::systemEnvironment().value("HOME", QString("??"));
3573 str += "/.kde4/share/config/kdeglobals";
3574 bool done = false;
3575 if (QFile::exists(str)) {
3576 QFile fln(str);
3577 if (!fln.open(QIODevice::ReadOnly | QIODevice::Text))
3578 return false;
3579 QTextStream fin(&fln);
3580 QString line("");
3581 while (!fin.atEnd() && !done) {
3582 line = fin.readLine();
3583 if (line.contains("ColorScheme")) {
3584 if (line.contains("dark", Qt::CaseInsensitive)) {
3585 fDarkMenuIcon = true;
3586 fDarkToolBarIcon = true;
3587 }
3588 done = true;
3589 }
3590 }
3591 fln.close();
3592 }
3593 return done;
3594 }
3595
3596 if (str.contains("dark", Qt::CaseInsensitive)) {
3597 fDarkMenuIcon = true;
3598 if (str.contains("ubuntu", Qt::CaseInsensitive) ||
3599 str.contains("xfce", Qt::CaseInsensitive) ||
3600 str.contains("mx", Qt::CaseInsensitive)) {
3601 fDarkMenuIcon = false;
3602 fDarkToolBarIcon = false;
3603 } else {
3604 fDarkToolBarIcon = true;
3605 }
3606 }
3607
3608 return true;
3609}
3610
3611//----------------------------------------------------------------------------------------------------
3616{
3617 for (int i=0; i<fAdmin->getNumRecentFiles(); i++) {
3618 fRecentFilesAction[i]->setText(fAdmin->getRecentFile(i));
3619 fRecentFilesAction[i]->setVisible(true);
3620 }
3621}
3622
3623//----------------------------------------------------------------------------------------------------
3633QStringList PTextEdit::getRunList(QString runListStr, bool &ok)
3634{
3635 QStringList result;
3636 bool isInt;
3637 QString str;
3638
3639 ok = true;
3640
3641 // first split space separated parts
3642 QStringList tok = runListStr.split(' ', Qt::SkipEmptyParts);
3643 for (int i=0; i<tok.size(); i++) {
3644 if (tok[i].contains('-')) { // list given, hence need to expand
3645 QStringList runListTok = tok[i].split('-', Qt::SkipEmptyParts);
3646 if (runListTok.size() != 2) { // error
3647 ok = false;
3648 result.clear();
3649 return result;
3650 }
3651 int start=0, end=0;
3652 start = runListTok[0].toInt(&isInt);
3653 if (!isInt) {
3654 ok = false;
3655 result.clear();
3656 return result;
3657 }
3658 end = runListTok[1].toInt(&isInt);
3659 if (!isInt) {
3660 ok = false;
3661 result.clear();
3662 return result;
3663 }
3664 for (int i=start; i<=end; i++) {
3665 str = QString("%1").arg(i);
3666 result << str;
3667 }
3668 } else if (tok[i].contains(':')) { // list given, hence need to expand
3669 QStringList runListTok = tok[i].split(':', Qt::SkipEmptyParts);
3670 int start{0}, end{0}, step{0};
3671 if (runListTok.size() != 3) { // error
3672 ok = false;
3673 result.clear();
3674 return result;
3675 }
3676 start = runListTok[0].toInt(&isInt);
3677 if (!isInt) {
3678 ok = false;
3679 result.clear();
3680 return result;
3681 }
3682 end = runListTok[1].toInt(&isInt);
3683 if (!isInt) {
3684 ok = false;
3685 result.clear();
3686 return result;
3687 }
3688 step = runListTok[2].toInt(&isInt);
3689 if (!isInt) {
3690 ok = false;
3691 result.clear();
3692 return result;
3693 }
3694 do {
3695 str = QString("%1").arg(start);
3696 result << str;
3697 start += step;
3698 } while (start <= end);
3699 } else { // keep it
3700 result << tok[i];
3701 }
3702 }
3703
3704 return result;
3705}
3706
3707//----------------------------------------------------------------------------------------------------
3714bool PTextEdit::fileAlreadyOpen(QFileInfo &finfo, int &idx)
3715{
3716 bool result = false;
3717 QFileInfo finfo2;
3718 QString tabFln;
3719
3720 for (int i=0; i<fTabWidget->count(); i++) {
3721 tabFln = *fFilenames.find( dynamic_cast<PSubTextEdit*>(fTabWidget->widget(i)));
3722 finfo2.setFile(tabFln);
3723 if (finfo.absoluteFilePath() == finfo2.absoluteFilePath()) {
3724 result = true;
3725 idx = i;
3726 break;
3727 }
3728 }
3729
3730 return result;
3731}
3732
3733//----------------------------------------------------------------------------------------------------
3738{
3739 if (fAdmin->getDarkThemeIconsMenuFlag()) { // dark theme icons
3740 fActions["New"]->setIcon(QIcon(":/icons/document-new-dark.svg"));
3741 fActions["Open"]->setIcon(QIcon(":/icons/document-open-dark.svg"));
3742 fActions["Reload"]->setIcon(QIcon(":/icons/view-refresh-dark.svg"));
3743 fActions["Save"]->setIcon(QIcon(":/icons/document-save-dark.svg"));
3744 fActions["Print"]->setIcon(QIcon(":/icons/document-print-dark.svg"));
3745 fActions["Undo"]->setIcon(QIcon(":/icons/edit-undo-dark.svg"));
3746 fActions["Redo"]->setIcon(QIcon(":/icons/edit-redo-dark.svg"));
3747 fActions["Copy"]->setIcon(QIcon(":/icons/edit-copy-dark.svg"));
3748 fActions["Cut"]->setIcon(QIcon(":/icons/edit-cut-dark.svg"));
3749 fActions["Paste"]->setIcon(QIcon(":/icons/edit-paste-dark.svg"));
3750 fActions["Find"]->setIcon(QIcon(":/icons/edit-find-dark.svg"));
3751 fActions["Find Next"]->setIcon(QIcon(":/icons/go-next-use-dark.svg"));
3752 fActions["Find Previous"]->setIcon(QIcon(":/icons/go-previous-use-dark.svg"));
3753 fActions["musrWiz"]->setIcon(QIcon(":/icons/musrWiz-32x32-dark.svg"));
3754 fActions["calcChisq"]->setIcon(QIcon(":/icons/musrchisq-dark.svg"));
3755 fActions["musrfit"]->setIcon(QIcon(":/icons/musrfit-dark.svg"));
3756 fActions["Swap Msr/Mlog"]->setIcon(QIcon(":/icons/musrswap-dark.svg"));
3757 fActions["musrStep"]->setIcon(QIcon(":/icons/musrStep-32x32-dark.svg"));
3758 fActions["msr2data"]->setIcon(QIcon(":/icons/msr2data-dark.svg"));
3759 fActions["mupp"]->setIcon(QIcon(":/icons/mupp-dark.svg"));
3760 fActions["musrview2dat"]->setIcon(QIcon(":/icons/musrview2dat-dark.svg"));
3761 fActions["musrview"]->setIcon(QIcon(":/icons/musrview-dark.svg"));
3762 fActions["musrt0"]->setIcon(QIcon(":/icons/musrt0-dark.svg"));
3763 fActions["musrFT"]->setIcon(QIcon(":/icons/musrFT-dark.svg"));
3764 fActions["musrprefs"]->setIcon(QIcon(":/icons/musrprefs-dark.svg"));
3765 fActions["musrdump"]->setIcon(QIcon(":/icons/musrdump-dark.svg"));
3766 } else { // plain theme icons
3767 fActions["New"]->setIcon(QIcon(":/icons/document-new-plain.svg"));
3768 fActions["Open"]->setIcon(QIcon(":/icons/document-open-plain.svg"));
3769 fActions["Reload"]->setIcon(QIcon(":/icons/view-refresh-plain.svg"));
3770 fActions["Save"]->setIcon(QIcon(":/icons/document-save-plain.svg"));
3771 fActions["Print"]->setIcon(QIcon(":/icons/document-print-plain.svg"));
3772 fActions["Undo"]->setIcon(QIcon(":/icons/edit-undo-plain.svg"));
3773 fActions["Redo"]->setIcon(QIcon(":/icons/edit-redo-plain.svg"));
3774 fActions["Copy"]->setIcon(QIcon(":/icons/edit-copy-plain.svg"));
3775 fActions["Cut"]->setIcon(QIcon(":/icons/edit-cut-plain.svg"));
3776 fActions["Paste"]->setIcon(QIcon(":/icons/edit-paste-plain.svg"));
3777 fActions["Find"]->setIcon(QIcon(":/icons/edit-find-plain.svg"));
3778 fActions["Find Next"]->setIcon(QIcon(":/icons/go-next-use-plain.svg"));
3779 fActions["Find Previous"]->setIcon(QIcon(":/icons/go-previous-use-plain.svg"));
3780 fActions["musrWiz"]->setIcon(QIcon(":/icons/musrWiz-32x32.svg"));
3781 fActions["calcChisq"]->setIcon(QIcon(":/icons/musrchisq-plain.svg"));
3782 fActions["musrfit"]->setIcon(QIcon(":/icons/musrfit-plain.svg"));
3783 fActions["Swap Msr/Mlog"]->setIcon(QIcon(":/icons/musrswap-plain.svg"));
3784 fActions["musrStep"]->setIcon(QIcon(":/icons/musrStep-32x32.svg"));
3785 fActions["msr2data"]->setIcon(QIcon(":/icons/msr2data-plain.svg"));
3786 fActions["mupp"]->setIcon(QIcon(":/icons/mupp-plain.svg"));
3787 fActions["musrview2dat"]->setIcon(QIcon(":/icons/musrview2dat-plain.svg"));
3788 fActions["musrview"]->setIcon(QIcon(":/icons/musrview-plain.svg"));
3789 fActions["musrt0"]->setIcon(QIcon(":/icons/musrt0-plain.svg"));
3790 fActions["musrFT"]->setIcon(QIcon(":/icons/musrFT-plain.svg"));
3791 fActions["musrprefs"]->setIcon(QIcon(":/icons/musrprefs-plain.svg"));
3792 fActions["musrdump"]->setIcon(QIcon(":/icons/musrdump-plain.svg"));
3793 }
3794}
3795
3796//----------------------------------------------------------------------------------------------------
3801{
3802 if (fAdmin->getDarkThemeIconsToolbarFlag()) { // dark theme icons
3803 fActions["New-tb"]->setIcon(QIcon(":/icons/document-new-dark.svg"));
3804 fActions["Open-tb"]->setIcon(QIcon(":/icons/document-open-dark.svg"));
3805 fActions["Reload-tb"]->setIcon(QIcon(":/icons/view-refresh-dark.svg"));
3806 fActions["Save-tb"]->setIcon(QIcon(":/icons/document-save-dark.svg"));
3807 fActions["Print-tb"]->setIcon(QIcon(":/icons/document-print-dark.svg"));
3808 fActions["Undo-tb"]->setIcon(QIcon(":/icons/edit-undo-dark.svg"));
3809 fActions["Redo-tb"]->setIcon(QIcon(":/icons/edit-redo-dark.svg"));
3810 fActions["Copy-tb"]->setIcon(QIcon(":/icons/edit-copy-dark.svg"));
3811 fActions["Cut-tb"]->setIcon(QIcon(":/icons/edit-cut-dark.svg"));
3812 fActions["Paste-tb"]->setIcon(QIcon(":/icons/edit-paste-dark.svg"));
3813 fActions["Find-tb"]->setIcon(QIcon(":/icons/edit-find-dark.svg"));
3814 fActions["Find Next-tb"]->setIcon(QIcon(":/icons/go-next-use-dark.svg"));
3815 fActions["Find Previous-tb"]->setIcon(QIcon(":/icons/go-previous-use-dark.svg"));
3816 fActions["musrWiz-tb"]->setIcon(QIcon(":/icons/musrWiz-32x32-dark.svg"));
3817 fActions["calcChisq-tb"]->setIcon(QIcon(":/icons/musrchisq-dark.svg"));
3818 fActions["musrfit-tb"]->setIcon(QIcon(":/icons/musrfit-dark.svg"));
3819 fActions["Swap Msr/Mlog-tb"]->setIcon(QIcon(":/icons/musrswap-dark.svg"));
3820 fActions["musrStep-tb"]->setIcon(QIcon(":/icons/musrStep-32x32-dark.svg"));
3821 fActions["msr2data-tb"]->setIcon(QIcon(":/icons/msr2data-dark.svg"));
3822 fActions["mupp-tb"]->setIcon(QIcon(":/icons/mupp-dark.svg"));
3823 fActions["musrview2dat-tb"]->setIcon(QIcon(":/icons/musrview2dat-dark.svg"));
3824 fActions["musrview-tb"]->setIcon(QIcon(":/icons/musrview-dark.svg"));
3825 fActions["musrt0-tb"]->setIcon(QIcon(":/icons/musrt0-dark.svg"));
3826 fActions["musrFT-tb"]->setIcon(QIcon(":/icons/musrFT-dark.svg"));
3827 fActions["musrprefs-tb"]->setIcon(QIcon(":/icons/musrprefs-dark.svg"));
3828 fActions["musrdump-tb"]->setIcon(QIcon(":/icons/musrdump-dark.svg"));
3829 } else { // plain theme icons
3830 fActions["New-tb"]->setIcon(QIcon(":/icons/document-new-plain.svg"));
3831 fActions["Open-tb"]->setIcon(QIcon(":/icons/document-open-plain.svg"));
3832 fActions["Reload-tb"]->setIcon(QIcon(":/icons/view-refresh-plain.svg"));
3833 fActions["Save-tb"]->setIcon(QIcon(":/icons/document-save-plain.svg"));
3834 fActions["Print-tb"]->setIcon(QIcon(":/icons/document-print-plain.svg"));
3835 fActions["Undo-tb"]->setIcon(QIcon(":/icons/edit-undo-plain.svg"));
3836 fActions["Redo-tb"]->setIcon(QIcon(":/icons/edit-redo-plain.svg"));
3837 fActions["Copy-tb"]->setIcon(QIcon(":/icons/edit-copy-plain.svg"));
3838 fActions["Cut-tb"]->setIcon(QIcon(":/icons/edit-cut-plain.svg"));
3839 fActions["Paste-tb"]->setIcon(QIcon(":/icons/edit-paste-plain.svg"));
3840 fActions["Find-tb"]->setIcon(QIcon(":/icons/edit-find-plain.svg"));
3841 fActions["Find Next-tb"]->setIcon(QIcon(":/icons/go-next-use-plain.svg"));
3842 fActions["Find Previous-tb"]->setIcon(QIcon(":/icons/go-previous-use-plain.svg"));
3843 fActions["musrWiz-tb"]->setIcon(QIcon(":/icons/musrWiz-32x32.svg"));
3844 fActions["calcChisq-tb"]->setIcon(QIcon(":/icons/musrchisq-plain.svg"));
3845 fActions["musrfit-tb"]->setIcon(QIcon(":/icons/musrfit-plain.svg"));
3846 fActions["Swap Msr/Mlog-tb"]->setIcon(QIcon(":/icons/musrswap-plain.svg"));
3847 fActions["musrStep-tb"]->setIcon(QIcon(":/icons/musrStep-32x32.svg"));
3848 fActions["msr2data-tb"]->setIcon(QIcon(":/icons/msr2data-plain.svg"));
3849 fActions["mupp-tb"]->setIcon(QIcon(":/icons/mupp-plain.svg"));
3850 fActions["musrview2dat-tb"]->setIcon(QIcon(":/icons/musrview2dat-plain.svg"));
3851 fActions["musrview-tb"]->setIcon(QIcon(":/icons/musrview-plain.svg"));
3852 fActions["musrt0-tb"]->setIcon(QIcon(":/icons/musrt0-plain.svg"));
3853 fActions["musrFT-tb"]->setIcon(QIcon(":/icons/musrFT-plain.svg"));
3854 fActions["musrprefs-tb"]->setIcon(QIcon(":/icons/musrprefs-plain.svg"));
3855 fActions["musrdump-tb"]->setIcon(QIcon(":/icons/musrdump-plain.svg"));
3856 }
3857}
3858
3859//----------------------------------------------------------------------------------------------------
3860// END
3861//----------------------------------------------------------------------------------------------------
Administration and configuration management for musredit.
Dialog for displaying dump_header command output.
Find dialog for text searching in musredit.
Dialog for displaying musrfit fitting process output.
Dialog for configuring musrFT command-line options.
Dialog interface for the msr2data batch processing tool.
About dialog for the musredit application.
Preferences dialog for musredit application settings.
Confirmation dialog for find-and-replace operations in musredit.
Find and replace dialog for the musredit text editor.
Enhanced text editor widget for editing msr files in musredit.
Main window class for the musredit application.
Dialog for executing and displaying dump_header command output.
Dialog for searching text in the editor.
Definition PFindDialog.h:89
virtual PFindReplaceData * getData()
Retrieves the search parameters from the dialog.
Dialog for executing and monitoring musrfit fitting processes.
Dialog for configuring musrFT Fourier transform tool options.
QStringList getMusrFTOptions()
Builds and returns the musrFT command-line options.
Dialog for configuring msr2data batch processing parameters.
virtual int getRunTag()
Returns the run input method tag.
virtual PMsr2DataParam * getMsr2DataParam()
Retrieves all msr2data parameters from the dialog.
About dialog displaying version and build information.
Preferences dialog for configuring musredit and musrfit settings.
int getTimeout()
Returns the fitting timeout preference.
bool getEstimateN0Flag()
Returns the N0 estimation preference.
bool getMusrviewShowFourierFlag()
Returns the musrview Fourier display preference.
bool getMusrviewShowAvgFlag()
Returns the musrview average display preference.
int getDump()
Returns the dump format preference.
bool getTitleFromDataFileFlag()
Returns the title-from-data-file preference.
bool getMusrviewShowOneToOneFlag()
Returns the musrview one-to-one plotting preference.
bool getEnableMusrT0Flag()
Returns the musrT0 enablement preference.
bool getYamlOutFlag()
Returns the YAML output preference.
bool getDarkThemeIconsToolbarFlag()
Returns the dark theme toolbar icons preference.
bool getDarkThemeIconsMenuFlag()
Returns the dark theme menu icons preference.
bool getIgnoreThemeAutoDetection()
Returns the theme auto-detection override preference.
bool getKeepRunPerBlockChisqFlag()
Returns the per-run chi-square preference.
bool getKeepMinuit2OutputFlag()
Returns the MINUIT2 output preservation preference.
Confirmation dialog for interactive find-and-replace operations.
Find and replace dialog for text editing operations.
virtual PFindReplaceData * getData()
Retrieves updated find/replace parameters from the dialog.
Enhanced text editor for msr file editing with block insertion support.
void insertTheoryBlock()
Slot: Inserts a THEORY block via dialog.
void insertPlotBlock()
Slot: Inserts a PLOT block via dialog.
void insertFourierBlock()
Slot: Inserts a FOURIER block via dialog.
void insertFunctionBlock()
Slot: Inserts a FUNCTIONS block via dialog.
void insertTitle()
Slot: Inserts a title block via dialog.
void insertParameterBlock()
Slot: Inserts a FITPARAMETER block via dialog.
void insertNonMusrRunBlock()
Slot: Inserts a non-µSR RUN block via dialog.
void insertStatisticBlock()
Slot: Inserts a default STATISTIC block.
void insertTheoryFunction(QString name)
Slot: Inserts a specific theory function.
void insertCommandBlock()
Slot: Inserts a default COMMANDS block.
int getFitType()
Retrieves the fit type from the current msr file content.
void insertSingleHistRunBlock()
Slot: Inserts a single histogram RUN block via dialog.
void insertAsymRunBlock()
Slot: Inserts an asymmetry RUN block via dialog.
void exitStatusMusrWiz(int exitCode, QProcess::ExitStatus exitStatus)
Slot: Handles exit status of musrWiz process.
void insertTheoryBlock()
Slot: Inserts a THEORY block into the current editor.
void replaceAll()
Slot: Replaces all occurrences without prompting.
QMap< QString, QAction * > fActions
Definition PTextEdit.h:966
QString fLastDirInUse
string holding the path from where the last file was loaded.
Definition PTextEdit.h:961
void setupFileActions()
Initializes File menu and toolbar actions.
std::unique_ptr< QComboBox > fComboSize
combo box for the font size
Definition PTextEdit.h:973
void musrView()
Slot: Launches musrView for viewing fit results.
PMsr2DataParam * fMsr2DataParam
structure holding the necessary input information for msr2data
Definition PTextEdit.h:969
QStringList getRunList(QString runListStr, bool &ok)
Parses a run list string into individual run numbers.
QTimer fFileSystemWatcherTimeout
timer used to re-enable file system watcher. Needed to delay the re-enabling
Definition PTextEdit.h:960
bool fileAlreadyOpen(QFileInfo &finfo, int &idx)
Checks if a file is already open in a tab.
void editUndo()
Slot: Undo last edit operation.
void fileCloseAll()
Slot: Closes all open tabs.
void editComment()
Slot: Comments out selected lines.
std::unique_ptr< QComboBox > fComboFont
combo box for the font selector
Definition PTextEdit.h:972
void musrDump()
Slot: Dumps raw histogram data from run files.
void applyFontSettings(int)
Slot: Applies font settings when tab changes.
void fileSystemWatcherActivation()
Manages file system watcher activation state.
void musrWiz()
Slot: Launches musrWiz (msr file creation wizard).
bool fFileSystemWatcherActive
flag to enable/disable the file system watcher
Definition PTextEdit.h:959
void fileSaveAs()
Slot: Saves the current file with a new name.
void close()
Signal: Emitted when the main window is closing.
void load(const QString &f, const int index=-1)
Loads a file into the editor.
void editCut()
Slot: Cut selected text to clipboard.
void fontChanged(const QFont &f)
Slot: Responds to font changes in editor.
PTextEdit(QWidget *parent=nullptr)
Constructs the main musredit window.
void setupHelpActions()
Initializes Help menu actions.
bool fFontChanging
flag needed to prevent some textChanged feature to occure when only the font changed
Definition PTextEdit.h:974
void aboutToQuit()
Slot: Cleanup handler called before application quits.
void fileSavePrefs()
Slot: Saves the preferences file.
PFindReplaceData * fFindReplaceData
structure holding the ncessary input for find/replace
Definition PTextEdit.h:970
void musrCalcChisq()
Slot: Calculates chi-square for current msr file.
void insertFunctionBlock()
Slot: Inserts a FUNCTIONS block into the current editor.
QMap< PSubTextEdit *, QString > fFilenames
mapper between tab widget object and filename
Definition PTextEdit.h:978
void fillRecentFiles()
Populates the Recent Files menu.
bool getTheme()
Detects the current system theme.
void textChanged(const bool forced=false)
Slot: Responds to text changes in editor.
void musrSetSteps()
Slot: Launches musrStep for setting fit step sizes.
std::unique_ptr< QFileSystemWatcher > fFileSystemWatcher
checks if msr-files are changing on the disk while being open in musredit.
Definition PTextEdit.h:958
void fileSave()
Slot: Saves the current file.
void musrFit()
Slot: Executes fit with current msr file.
void helpContents()
Slot: Opens online documentation.
void helpAboutQt()
Slot: Displays Qt About dialog.
QAction * fRecentFilesAction[MAX_RECENT_FILES]
array of the recent file actions
Definition PTextEdit.h:981
bool fDarkToolBarIcon
flag indicating if a dark or plain icon shall be used in the toolbar
Definition PTextEdit.h:956
QStringList fMusrFTPrevCmd
Definition PTextEdit.h:962
void fileOpenPrefs()
Slot: Opens the preferences file in a new tab.
void fileCloseAllOthers()
Slot: Closes all tabs except the current one.
void setupMusrActions()
Initializes Musr menu and toolbar actions.
void setupTextActions()
Initializes Text menu and toolbar actions.
void editUncomment()
Slot: Uncomments selected lines.
void insertTheoryFunction(QAction *a)
Slot: Inserts a specific theory function into the current editor.
void switchToolbarIcons()
Switches toolbar icons between dark and plain variants.
void editRedo()
Slot: Redo previously undone edit operation.
void insertParameterBlock()
Slot: Inserts a FITPARAMETER block into the current editor.
void insertCommandBlock()
Slot: Inserts a COMMANDS block into the current editor.
void fileChanged(const QString &fileName)
Slot: Handles file system watcher notifications.
std::unique_ptr< PAdmin > fAdmin
pointer to the xml-startup file informations. Needed for different purposes like default working- and...
Definition PTextEdit.h:957
void insertTitle()
Slot: Inserts a title block into the current editor.
void helpAbout()
Slot: Displays musredit About dialog.
void editSelectAll()
Slot: Select all text in current editor.
void fileExit()
Slot: Exits the application.
void editFindAndReplace()
Slot: Opens find and replace dialog.
void musrSwapMsrMlog()
Slot: Swaps between .msr and .mlog files.
void setFileSystemWatcherActive()
Slot: Re-enables file system watcher after delay.
PSubTextEdit * currentEditor() const
Gets the currently active editor widget.
void insertPlotBlock()
Slot: Inserts a PLOT block into the current editor.
QStatusBar * fStatusBar
Definition PTextEdit.h:964
void insertNonMusrRunBlock()
Slot: Inserts a non-µSR RUN block into the current editor.
std::unique_ptr< QComboBox > fJumpToBlock
combo box used to jump to the msr-file blocks
Definition PTextEdit.h:975
void editFindNext()
Slot: Finds next occurrence of search text.
void musrView2Dat()
Slot: Launches musrView in 2-data file mode.
void replace()
Slot: Replaces current match and finds next occurrence.
void mupp()
Slot: Launches mupp (muon parameter plot).
void textFamily(const QString &f)
Slot: Changes font family for current editor.
void setupEditActions()
Initializes Edit menu and toolbar actions.
void editFind()
Slot: Opens find dialog.
std::unique_ptr< QAction > fMusrT0Action
Definition PTextEdit.h:967
void currentCursorPosition()
Slot: Updates status bar with current cursor position.
void setupJumpToBlock()
Initializes the Jump to Block combo box.
void musrFT()
Slot: Opens Fourier transform dialog.
void fileReload()
Slot: Reloads the current file from disk.
void filePrint()
Slot: Prints the current file.
void editFindPrevious()
Slot: Finds previous occurrence of search text.
void editCopy()
Slot: Copy selected text to clipboard.
void musrPrefs()
Slot: Opens preferences dialog.
void insertAsymRunBlock()
Slot: Inserts an asymmetry RUN block into the current editor.
void fileOpen()
Slot: Opens a file dialog to load an msr file.
void insertSingleHistRunBlock()
Slot: Inserts a single histogram RUN block into the current editor.
void insertStatisticBlock()
Slot: Inserts a STATISTIC block into the current editor.
void switchMenuIcons()
Switches menu icons between dark and plain variants.
void insertFourierBlock()
Slot: Inserts a FOURIER block into the current editor.
void fileOpenRecent()
Slot: Opens a recently used file.
void textSize(const QString &p)
Slot: Changes font size for current editor.
void exitStatusMusrSetSteps(int exitCode, QProcess::ExitStatus exitStatus)
Slot: Handles exit status of musrSetSteps process.
void jumpToBlock(int idx)
Slot: Jumps cursor to selected msr file block.
void musrT0()
Slot: Opens musrT0 dialog for determining t0 timing parameter.
bool fDarkMenuIcon
flag indicating if a dark or plain icon shall be used in the menu pull-downs
Definition PTextEdit.h:955
void musrMsr2Data()
Slot: Opens msr2data conversion dialog.
std::unique_ptr< QTabWidget > fTabWidget
tab widget in which the text editor(s) are placed
Definition PTextEdit.h:977
void editPaste()
Slot: Paste text from clipboard at cursor position.
void doConnections(PSubTextEdit *e)
Establishes signal-slot connections for an editor.
void fileClose(const bool check=true)
Slot: Closes the current tab.
QMenu * fRecentFilesMenu
recent file menu
Definition PTextEdit.h:980
void fileNew()
Slot: Creates a new empty msr file in a new tab.
void replaceAndClose()
Slot: Replaces current match and closes replace dialog.
#define MAX_RECENT_FILES
Maximum number of recently opened files to track.
Definition musredit.h:55
Configuration structure for find and replace operations.
Definition musredit.h:109
Parameter structure for msr2data tool integration.
Definition musredit.h:73
Structure holding information about a musrfit theory function.
Definition PAdmin.h:90
QString label
Short label for GUI menus and buttons.
Definition PAdmin.h:93