source: palm/trunk/UTIL/mrungui/mainwindow.cpp @ 1791

Last change on this file since 1791 was 1724, checked in by boeske, 9 years ago

Last commit documented

  • Property svn:keywords set to Id
File size: 47.1 KB
RevLine 
[1046]1//------------------------------------------------------------------------------//
2// This file is part of PALM.
3//
4// PALM is free software: you can redistribute it and/or modify it under the terms
5// of the GNU General Public License as published by the Free Software Foundation,
6// either version 3 of the License, or (at your option) any later version.
7//
8// PALM is distributed in the hope that it will be useful, but WITHOUT ANY
9// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
10// A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
11//
12// You should have received a copy of the GNU General Public License along with
13// PALM. If not, see <http://www.gnu.org/licenses/>.
14//
15// Copyright 1997-2012  Leibniz University Hannover
16//--------------------------------------------------------------------------------//
17//
[793]18// Current revisions:
19// -----------------
[1612]20//
[793]21//
22// Former revisions:
23// -----------------
24// $Id: mainwindow.cpp 1724 2015-11-16 15:42:34Z raasch $
25//
[1724]26// 1723 2015-11-16 15:25:51Z boeske
27// Added checkbox for cyclic fill flag in mrungui
28//
[1612]29// 1611 2015-07-07 12:23:22Z maronga
30// Added routine start_watchdog.
31//
[1047]32// 1046 2012-11-09 14:38:45Z maronga
33// code put under GPL (PALM 3.9)
34//
[921]35// mainwindow.cpp 920 2012-06-05 09:56:53Z maronga
36// Added -Z option (disable combine_plot_fields)
37//
[819]38// 818 2012-02-08 16:11:23Z maronga
39// New: flag parameter -z implemented (used for skipping parameter file check)
40//
[812]41// 811 2012-01-31 09:45:54Z maronga
42// Bugfix: waitForFinished time exceeded limits, adjusted to 1h waiting time
43//
[810]44// 809 2012-01-30 13:32:58Z marong
45// Bugfix: waiting for 20 minutes does not suffice for local runs
46//
[794]47// 793 2011-12-12 15:15:24Z maronga
48// Initial revision
49//
[793]50// Description:
51// ------------
52// All subroutines for mrungui
53//----------------------------------------------------------------------------//
54
55#include <QtGui/QApplication>
56#include "mainwindow.h"
57#include "ui_mainwindow.h"
58#include "ui_about.h"
59#include "ui_help.h"
60#include <QString>
61#include <QFileDialog>
62#include <QDateTime>
63#include "stdlib.h"
64#include <QProcess>
65#include <QTextStream>
66
67
68// Define username on host as global variable
69QString username = getenv("USER");
70// Define variable branch (location of mrungui, e.g.
71// "/home/user/palm/current_version"
72QString branch;
73
74
75//****************************************************************************//
76//  Initialization of the main window
77MainWindow::MainWindow(QWidget *parent) :
78    QMainWindow(parent),
79    ui(new Ui::MainWindow)
80{
81    ui->setupUi(this);
82
83//  Empty the mrun command line (hereafter mrunline)
84    ui->commandline->setText("");
85
86//  Get path of the program and set default file
87    branch = QCoreApplication::applicationDirPath();
88    branch = branch.left(branch.length() - 14);
89
90
91    QFile file(branch+"/.mrun.gui.default");
92
93//  Read default settings
94    if ( file.exists() == true && file.size() > 10)
95    {
96
97       QString mrunline;
98       if ( file.open(QIODevice::ReadOnly | QIODevice::Text ) )
99       {
100
101//        File opened successfully
102          QTextStream in(&file);
103
104          QString line = in.readLine();
105          while (!line.isNull())
106          {
107             mrunline = line;
108             line = in.readLine();
109          }
110
111          file.close();
112       }
113
114       mrunline = mrunline.right(mrunline.length() - 17);
115       ui->commandline->setText(mrunline);
116
117       setup_gui(mrunline);
118
119    }
120
121//  Load jobs into the recent jobs list
122    recent_jobs(10);
123}
124
125
126//****************************************************************************//
127//  Routine for listing jobs in the recent jobs list
128int MainWindow::recent_jobs(int noj)
129{
130    branch = QCoreApplication::applicationDirPath();
131    branch = branch.left(branch.length() - 14);
132
133    QFile file(branch+"/.mrun.history");
134    QString listitem, timestamp;
135
136//  Read mrun history and select the last used jobs
137    if ( file.exists() == true && file.size() > 10)
138    {
139
140//     Open history
141       QStringList history, tmphistory;
142       if ( file.open(QIODevice::ReadOnly | QIODevice::Text ) )
143       {
144
145//        file opened successfully
146          QTextStream in(&file);
147
148          QString line = in.readLine();
149          while (!line.isNull())
150          {
151             history.append(line);
152             line = in.readLine();
153          }
154
155          file.close();
156       }
157
158       int j = 0;
159
160       ui->list_jobname->clear();
161
162//     Read history entries and append to recent job list
163       for (int i=history.count(); i>=1; i--)
164       {
165           timestamp = history[i-1].left(16);
166           listitem = history[i-1].right(history[i-1].length() - 17);
167           listitem = listitem.split("-d ", QString::SkipEmptyParts)[1];
168           listitem = listitem.split(" -", QString::SkipEmptyParts)[0];
169           listitem = listitem.replace(" ","");
170
171           QList<QListWidgetItem *> matchitems = \
172                   ui->list_jobname->findItems(listitem, Qt::MatchExactly);
173
174           if ( matchitems.count() == 0 )
175           {
176              ui->list_jobname->addItem(listitem);
177              tmphistory.append(listitem+" ("+timestamp+")");
178              j++;
179           }
180           if ( j == noj )
181           {
182               break;
183           }
184       }
185
186//     Send to list
187       ui->list_jobname->clear();
188       for (int i=tmphistory.count(); i>=1; i--)
189       {
190           ui->list_jobname->addItem(tmphistory[i-1]);
191       }
192
193    }
194    return 0;
195}
196
197//****************************************************************************//
198//  Exit program
199MainWindow::~MainWindow()
200{
201
202    delete ui;
203}
204
205
206//****************************************************************************//
207//  Start the mrun command via xterm
208int MainWindow::startmrun()
209{
210
211    QString xtermoutput;
212    QString mrunline_save;
213    QString history_line;
214    QString mrunline = ui->commandline->text();
215    QString userline = ui->line_user->text();
216
217//  Check for empty line
218    mrunline_save = mrunline;
219    if (userline != "")
220    {
221        mrunline = mrunline + " " + userline;
222    }
223    history_line = mrunline;
224
225//  Disable the main window
226    ui->group_job->setEnabled(false);
227    ui->group_execution->setEnabled(false);
228    ui->group_runcontrol->setEnabled(false);
229    ui->group_advanced->setEnabled(false);
230    ui->check_advanced->setEnabled(false);
231    ui->check_verbose->setEnabled(false);
[818]232    ui->check_namelist_check->setEnabled(false);
[793]233    ui->button_start->setEnabled(false);
234    ui->button_start->setText("wait...");
235
236    branch = QCoreApplication::applicationDirPath();
237    branch = branch.left(branch.length() - 14);
238
239    ui->commandline->setText("Executing MRUN in xterm...");
240
241//  Wait until all commands have been executed (ugly)
242    for(int i=0; i<20; i++)
243       qApp->processEvents();
244
245//  Start xterm as QProcess
246    QProcess mrun;
247    mrun.setProcessChannelMode(QProcess::MergedChannels);
248    mrun.setWorkingDirectory(branch);
249
250    mrunline = " -title \"Executing MRUN...\" -geometry \"100x55+970+0\" -e \""\
251          +mrunline.replace("\"","\'")\
252          +";echo -n '--> Press Enter to continue...';read yesno\"";
253
254    mrun.start("xterm"+mrunline);
255
256    if(!mrun.waitForStarted())
257        return 0;
258
259//    while(mrun.waitForReadyRead())
260//        xtermoutput = xtermoutput+mrun.readAllStandardOutput();
261
[811]262//  Wait until mrun has finished or wait for 200 minutes
263    mrun.waitForFinished(3600000);
[793]264
265
266//  Jobs has been submitted or aborted. Continuing...
267//  Save the mrun command to history file
268    QString filename = branch+"/.mrun.history";
269
270    QDateTime time = QDateTime::currentDateTime();
271    QString tmptime = time.toString("yyyy/MM/dd hh:mm");
272
273    QFile file(filename);
274    file.open(QIODevice::Append | QIODevice::Text);
275    QTextStream out(&file);
276    out << tmptime + " " + history_line + "\n";
277    file.close();
278
279//  Enable main window again
280    ui->group_job->setEnabled(true);
281    ui->group_execution->setEnabled(true);
282    ui->group_runcontrol->setEnabled(true);
283    if ( ui->check_advanced->isChecked() == true)
284    {
285       ui->group_advanced->setEnabled(true);
286    }
287    ui->check_advanced->setEnabled(true);
288    ui->check_verbose->setEnabled(true);
[818]289    ui->check_namelist_check->setEnabled(true);
[793]290    ui->button_start->setEnabled(true);
291    ui->action_save->setEnabled(true);
292    ui->button_start->setText("MRUN Start");
293    ui->commandline->setText(mrunline_save);
294
295//  Reload recent jobs
296    recent_jobs(10);
297
298    return 0;
299}
300
301
302//****************************************************************************//
303//  Disable/Enable advanced settings dialog
304int MainWindow::enable_advanced()
305{
306    bool status;
307
308    status = ui->group_advanced->isEnabled();
309    if (status == true)
310    {
311       ui->group_advanced->setEnabled(false);
312    }
313    else
314    {
315       ui->group_advanced->setEnabled(true);
316    }
317
318    return 0;
319}
320
321
322//****************************************************************************//
323//  Disable/enable dialog for coupled runs
324int MainWindow::enable_coupled()
325{
326    QString status;
327
328    status = ui->drop_job->currentText();
329    if (status == "Coupled restart")
330    {
331       ui->label_coupled1->setEnabled(true);
332       ui->label_coupled2->setEnabled(true);
333       ui->label_coupled3->setEnabled(true);
334       ui->line_PE_atmos->setEnabled(true);
335       ui->line_PE_ocean->setEnabled(true);
336
337       QString pe_total = ui->line_pe->text();
338       QString pe_atmos = ui->line_PE_atmos->text();
339       QString pe_ocean = ui->line_PE_ocean->text();
340       if (pe_total != "")
341       {
342           int PE_split = pe_total.toInt()/2;
343           ui->line_PE_atmos->setText(QString::number(PE_split));
344           ui->line_PE_ocean->setText(QString::number(PE_split));
345       }
346    }
347    else
348    {
349        ui->label_coupled1->setEnabled(false);
350        ui->label_coupled2->setEnabled(false);
351        ui->label_coupled3->setEnabled(false);
352        ui->line_PE_atmos->setEnabled(false);
353        ui->line_PE_ocean->setEnabled(false);
354    }
355
356    return 0;
357}
358
359
360//****************************************************************************//
361//  Choose job from dialog
362int MainWindow::choosejob()
363{
364    QString filename;
365    branch = QCoreApplication::applicationDirPath();
366    branch = branch.left(branch.length() - 14);
367
368    QString jobdir = branch+"/JOBS";
369
370
371//  Pick a job from dialog
372    filename = QFileDialog::getExistingDirectory(this, \
373                            tr("Choose a job directory"), branch+"/JOBS", \
374               QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks | \
375               QFileDialog::DontUseNativeDialog | QFileDialog::ReadOnly | \
376               QFileDialog::DontConfirmOverwrite);
377
378
379
380
381
382//  If a file was selected, load it into mainwindow
383    if ( filename != "")
384    {
385        filename = filename.right(filename.length() - jobdir.length() - 1);
386
387        ui->line_jobname->setText(filename);
388        ui->list_jobname->clearSelection();
389
390//      Change mrunline accordingly
391        change_commandline("d","");
392        change_commandline("r","");
393        return 0;
394    }
395    else
396    {
397        return 1;
398    }
399}
400
401
402//****************************************************************************//
403//  Choose job from the recent job list and load all settings
404int MainWindow::choosejob_list()
405{
406    QString filename, timestamp, jobname;
407
408//  Get selected item from list
409    filename = ui->list_jobname->currentItem()->text();
410    int itemint = ui->list_jobname->currentRow();
411
412//  Reload list
413    ui->setupUi(this);
414    recent_jobs(10);
415
416//  Set selected item to jobname
417    ui->list_jobname->item(itemint)->setSelected(true);
418
419    timestamp = filename.right(17).left(16);
420    jobname = filename.left(filename.length() - 19);
421
422    branch = QCoreApplication::applicationDirPath();
423    branch = branch.left(branch.length() - 14);
424    QFile file(branch+"/.mrun.history");
425    QString listitem;
426
427//  Load history
428    if ( file.exists() == true && file.size() > 10)
429    {
430
431       QStringList history;
432       if ( file.open(QIODevice::ReadOnly | QIODevice::Text ) )
433       {
434
435//        file opened successfully
436          QTextStream in(&file);
437
438          QString line = in.readLine();
439          while (!line.isNull())
440          {
441             history.append(line);
442             line = in.readLine();
443          }
444
445          file.close();
446       }
447
448       for (int i=history.count(); i>=1; i--)
449       {
450           listitem = history[i-1].right(history[i-1].length() - 17);
451           listitem = listitem.split("-d ", QString::SkipEmptyParts)[1];
452           listitem = listitem.split(" -", QString::SkipEmptyParts)[0];
453           listitem = listitem.replace(" ","");
454
455
456//         Select command line with correct timestamp and jobname
457           if (history[i-1].left(16) == timestamp && listitem == jobname)
458           {
459              QString mrunline = history[i-1];
460              mrunline = mrunline.right(mrunline.length() - 17);
461              ui->commandline->setText(mrunline);
462
463              setup_gui(mrunline);
464           }
465       }
466    }
467
468     return 0;
469}
470
471
472//****************************************************************************//
473//  Change run identifer (initial, restart, coupled...)
474int MainWindow::change_rc_list()
475{
476
477
478   QString drop_job = ui->drop_job->currentText();
479
480   change_commandline("r","");
481
482// Enable PE distribution for atmosphere/ocean
483   if ( drop_job == "Coupled restart")
484   {
485       QString drop_atmos = ui->line_PE_atmos->text();
486       QString drop_ocean = ui->line_PE_ocean->text();
487
488       change_commandline("Y",drop_atmos+" "+drop_ocean);
489   }
490
491// Check of ocean runs
492   else
493   {
494      delete_commandline("Y");
495      if (drop_job == "Precursor run (Ocean)")
496      {
497          activate_flag("y");
498      }
499      else
500      {
501          deactivate_flag("y");
502      }
503   }
504
505
506    return 0;
507}
508
509
510//****************************************************************************//
511//  Routine for processing any changes in the mainwindow settings
512int MainWindow::change_commandline(QString id,QString fwstring)
513{
514
515//  First get the mrunline
516    QString newmrunline;
517    bool    initialize=false;
518
519    QString mrunline = ui->commandline->text();
520
521    QStringList splitline = mrunline.split(" -"+id+"", QString::SkipEmptyParts);
522    if ( splitline.count() == 1)
523    {
524        splitline.append(" ");
525    }
526    else if ( splitline.count() == 0 )
527    {
528       splitline.append("mrun");
529       splitline.append(" ");
530       initialize = true;
531    }
532
533    QStringList param = splitline[1].split("-");
534
535//  Change in parameter "d" (jobname)
536    if (id == "d")
537    {
538       QString filename = ui->line_jobname->text();
539
540       param[0] = filename.replace(" ","");
541
542       if ( initialize == true && ui->group_runcontrol->isEnabled() == true )
543       {
544           ui->group_runcontrol->setEnabled(true);
545           ui->group_execution->setEnabled(true);
546           ui->drop_job->setEnabled(true);
547           ui->check_advanced->setEnabled(true);
548           ui->button_start->setEnabled(true);
549           ui->action_save->setEnabled(true);
550       }
551       else if ( param[0] == "")
552       {
553           ui->group_runcontrol->setEnabled(false);
554           ui->group_execution->setEnabled(false);
555           ui->drop_job->setEnabled(false);
556           ui->button_start->setEnabled(false);
557           ui->action_save->setEnabled(false);
558           ui->group_advanced->setEnabled(false);
559           ui->check_advanced->setEnabled(false);
560           delete_commandline("d");
561           change_commandline("r","remove");
562           ui->label_usercode->setText("");
563           return 1;
564       }
565       else
566       {
567
568//         Check if user code is available
569           branch = QCoreApplication::applicationDirPath();
570           branch = branch.left(branch.length() - 14);
571           QDir usercode = branch+"/USER_CODE/"+param[0];
572           if (usercode.exists() == true)
573           {
574               ui->label_usercode->setText("User code found.");
575           }
576           else
577           {
578               ui->label_usercode->setText("Warning: no user code found!");
579           }
580
581//         Check if _pdf file is available, otherwise notice user
582           if (ui->check_restarts->checkState() == 2)
583           {
584              QString jobname = ui->line_jobname->text();
585              QFile restartfile(branch+"/JOBS/"+jobname+"/INPUT/"+jobname+"_p3df");
586              if (restartfile.exists() == true)
587              {
588                 ui->label_restart->setText("");
589              }
590              else
591              {
592                 ui->label_restart->setText("Warning: No p3df file found!");
593              }
594           }
595
596           ui->group_runcontrol->setEnabled(true);
597           ui->group_execution->setEnabled(true);
598           ui->drop_job->setEnabled(true);
599           ui->check_advanced->setEnabled(true);
600
601           if ( ui->check_advanced->isChecked() == true )
602           {
603              ui->group_advanced->setEnabled(true);
604              if ( ui->line_i->text() != "" || ui->line_o->text() != "")
605              {
606                 change_commandline("r","remove");
607                 ui->group_runcontrol->setEnabled(false);
608              }
609           }
610       }
611
612    }
613
614//  Change in parameter "r" (run control list)
615    else if (id == "r")
616    {
617        int status_ts = ui->check_ts->checkState();
618        int status_pr = ui->check_pr->checkState();
619        int status_xy = ui->check_xy->checkState();
620        int status_xz = ui->check_xz->checkState();
621        int status_yz = ui->check_yz->checkState();
622        int status_3d = ui->check_3d->checkState();
623        int status_ma = ui->check_ma->checkState();
624        int status_sp = ui->check_sp->checkState();
625        int status_pts = ui->check_pts->checkState();
626        int status_prt = ui->check_prt->checkState();
627
628        QString drop_job = ui->drop_job->currentText();
629        QString rc_flag = "#";
630
631        if (drop_job == "Initial run")
632        {
633            rc_flag = "#";
634        }
635        else if (drop_job == "Restart run")
636        {
637            rc_flag = "f";
638        }
639        else if (drop_job == "Precursor run (Atmosphere)")
640        {
641            rc_flag = "#";
642        }
643        else if (drop_job == "Precursor run (Ocean)")
644        {
645           rc_flag = "o#";
646        }
647        else if (drop_job == "Coupled restart")
648        {
649           rc_flag = "f";
650        }
651
652        param[0] = "\"d3"+rc_flag;
653
654        if (status_ts == 2)
655        {
656            param[0] = param[0]+" ts"+rc_flag;
657        }
658        if (status_pr == 2)
659        {
660           param[0] = param[0]+" pr"+rc_flag;
661        }
662        if (status_xy == 2)
663        {
664           param[0] = param[0]+" xy"+rc_flag;
665        }
666        if (status_xz == 2)
667        {
668           param[0] = param[0]+" xz"+rc_flag;
669        }
670        if (status_yz == 2)
671        {
672           param[0] = param[0]+" yz"+rc_flag;
673        }
674        if (status_3d == 2)
675        {
676           param[0] = param[0]+" 3d"+rc_flag;
677        }
678        if (status_ma == 2)
679        {
680           param[0] = param[0]+" ma"+rc_flag;
681        }
682        if (status_sp == 2)
683        {
684           param[0] = param[0]+" sp"+rc_flag;
685        }
686        if (status_prt == 2)
687        {
688           param[0] = param[0]+" prt"+rc_flag;
689        }
690        if (status_pts == 2)
691        {
692           param[0] = param[0]+" pts"+rc_flag;
693        }
694
695        if (drop_job == "Coupled restart")
696        {
697            rc_flag = "of";
698            param[0] = param[0]+" d3"+rc_flag;
699
700            if (status_ts == 2)
701            {
702                param[0] = param[0]+" ts"+rc_flag;
703            }
704            if (status_pr == 2)
705            {
706               param[0] = param[0]+" pr"+rc_flag;
707            }
708            if (status_xy == 2)
709            {
710               param[0] = param[0]+" xy"+rc_flag;
711            }
712            if (status_xz == 2)
713            {
714               param[0] = param[0]+" xz"+rc_flag;
715            }
716            if (status_yz == 2)
717            {
718               param[0] = param[0]+" yz"+rc_flag;
719            }
720            if (status_3d == 2)
721            {
722               param[0] = param[0]+" 3d"+rc_flag;
723            }
724            if (status_ma == 2)
725            {
726               param[0] = param[0]+" ma"+rc_flag;
727            }
728            if (status_sp == 2)
729            {
730               param[0] = param[0]+" sp"+rc_flag;
731            }
732            if (status_prt == 2)
733            {
734               param[0] = param[0]+" prt"+rc_flag;
735            }
736            if (status_pts == 2)
737            {
738               param[0] = param[0]+" pts"+rc_flag;
739            }
740        }
741
742        int status_restarts = ui->check_restarts->checkState();
743
744
745
746        if (status_restarts == 2)
747        {
748            param[0]=param[0]+" restart";
749
750//          Check if _pdf file is available, otherwise notice user
751            if (ui->check_restarts->checkState() == 2)
752            {
753               QString jobname = ui->line_jobname->text();
754               branch = QCoreApplication::applicationDirPath();
755               branch = branch.left(branch.length() - 14);
756               QFile restartfile(branch+"/JOBS/"+jobname+"/INPUT/"+jobname+ \
757                                 "_p3df");
758               if (restartfile.exists() == true)
759               {
760                  ui->label_restart->setText("");
761               }
762               else
763               {
764                  ui->label_restart->setText("Warning: No p3df file found!");
765               }
766            }
767
768        }
769        else  {
770          ui->label_restart->setText("");
771        }
772
[1723]773       
774       
775        int status_cycfill = ui->check_cycfill->checkState();
776
777        if (status_cycfill == 2)
778        {
779            param[0]=param[0]+" cycfill";
780        }
781
782
783       
[793]784        param[0]=param[0]+"\" ";
785
786        if ( fwstring == "remove")
787        {
788            delete_commandline(id);
789            return 1;
790        }
791        else
792        {
793           ui->button_start->setEnabled(true);
794           ui->action_save->setEnabled(true);
795        }
796    }
797//  Change in any other parameter
798    else
799    {
800        if ( fwstring != "")
801        {
802           param[0] = "\""+fwstring+"\"";
803        }
804        else
805        {
806            delete_commandline(id);
807            return 1;
808        }
809
810    }
811    param[0] = param[0] + " ";
812
813//  Join the new mrunline
814    splitline[1]= param.join("-");
815    newmrunline = splitline.join(" -"+id+" ");
816
817//  Print the new mrunline to mainwindow
818    newmrunline.replace("  "," ");
819    ui->commandline->setText(newmrunline);
820
821    return 0;
822}
823
824
825//****************************************************************************//
826//  Get all signals from mainwindow and perform change via change_commandline()
827int MainWindow::change_lineinput()
828{
829    QString tmptext;
830
831    if ( sender() == ui->line_host )
832    {
833        tmptext = ui->line_host->text();
834        change_commandline("h",tmptext);
835    }
836    else if ( sender() == ui->line_jobname)
837    {
838        tmptext = ui->line_jobname->text();
839        change_commandline("d",tmptext);
840    }
841    else if ( sender() == ui->line_q)
842    {
843        tmptext = ui->line_q->text();
844        change_commandline("q",tmptext);
845    }
846    else if ( sender() == ui->line_account)
847    {
848        tmptext = ui->line_account->text();
849        change_commandline("u",tmptext);
850    }
851    else if ( sender() ==  ui->line_pe)
852    {
853        tmptext = ui->line_pe->text();
854        change_commandline("X",tmptext);
855    }
856    else if ( sender() == ui->line_tpn)
857    {
858        tmptext = ui->line_tpn->text();
859        change_commandline("T",tmptext);
860    }
861    else if ( sender() == ui->line_branch)
862    {
863        tmptext = ui->line_branch->text();
864        change_commandline("K",tmptext);
865    }
866    else if ( sender() == ui->line_time)
867    {
868        tmptext = ui->line_time->text();
869        change_commandline("t",tmptext);
870    }
871    else if ( sender() == ui->line_M)
872    {
873        tmptext = ui->line_M->text();
874        change_commandline("M",tmptext);
875    }
876    else if ( sender() == ui->line_m)
877    {
878        tmptext = ui->line_m->text();
879        change_commandline("m",tmptext);
880    }
881    else if ( sender() == ui->line_a)
882    {
883        tmptext = ui->line_a->text();
884        change_commandline("a",tmptext);
885    }
886    else if ( sender() == ui->line_D)
887    {
888        tmptext = ui->line_D->text();
889        change_commandline("D",tmptext);
890    }
891    else if ( sender() == ui->line_c)
892    {
893        tmptext = ui->line_c->text();
894        if ( tmptext == ".mrun.config")
895        {
896            tmptext = "";
897        }
898        change_commandline("c",tmptext);
899    }
900    else if ( sender() == ui->line_p)
901    {
902        tmptext = ui->line_p->text();
903        change_commandline("p",tmptext);
904    }
905    else if ( sender() == ui->line_s)
906    {
907        tmptext = ui->line_s->text();
908        change_commandline("s",tmptext);
909    }
910    else if ( sender() == ui->line_i)
911    {
912        tmptext = ui->line_i->text();
913        if ( tmptext != "")
914        {
915            change_commandline("r","remove");
916            ui->group_runcontrol->setEnabled(false);
917
918            ui->button_start->setEnabled(true);
919            ui->action_save->setEnabled(true);
920        }
921        else if (ui->line_o->text() == "" )
922        {
923           ui->group_runcontrol->setEnabled(true);
924           change_commandline("r","");
925        }
926
927        change_commandline("i",tmptext);
928    }
929    else if ( sender() == ui->line_o)
930    {
931        tmptext = ui->line_o->text();
932        if ( tmptext != "")
933        {
934            change_commandline("r","remove");
935            ui->button_start->setEnabled(true);
936            ui->action_save->setEnabled(true);
937            ui->group_runcontrol->setEnabled(false);
938        }
939        else if (ui->line_i->text() == "" )
940        {
941           ui->group_runcontrol->setEnabled(true);
942           change_commandline("r","");
943        }
944
945        change_commandline("o",tmptext);
946
947    }
948    else if ( sender() == ui->line_w)
949    {
950        tmptext = ui->line_w->text();
951        change_commandline("w",tmptext);
952    }
953    else if ( sender() == ui->line_PE_atmos || sender() == ui->line_PE_ocean)
954    {
955        tmptext = ui->line_PE_atmos->text() + " "  + ui->line_PE_ocean->text();
956        change_commandline("Y",tmptext);
957        int PE_total = ui->line_PE_atmos->text().toInt() + \
958                        ui->line_PE_ocean->text().toInt();
959        ui->line_pe->setText(QString::number(PE_total));
960        change_commandline("X",QString::number(PE_total));
961    }
962
963    else if ( sender() == ui->combo_n)
964    {
965        tmptext = ui->combo_n->currentText();
966        if ( tmptext == "default")
967        {
968            tmptext = "";
969        }
970        change_commandline("n",tmptext);
971    }
972    else if ( sender() == ui->line_user)
973    {
974       return 0;
975    }
976
977    return 0;
978}
979
980
981//****************************************************************************//
982//  Delete a parameter from mrunline
983int MainWindow::delete_commandline(QString id)
984{
985
986//  Read mrunline
987    QString newmrunline;
988    QString mrunline = ui->commandline->text();
989    QStringList splitline = mrunline.split(" -"+id, QString::SkipEmptyParts);
990    if ( splitline.count() == 1)
991    {
992       return 0;
993    }
994    else
995    {
996       QStringList param = splitline[1].split("-");
997       param[0] = "";
998       splitline[1]= param.join(" -");
999       newmrunline = splitline.join("");
1000
1001//     Print new mrunline to screen
1002       ui->commandline->setText(newmrunline);
1003
1004       return 0;
1005    }
1006}
1007
1008
1009//****************************************************************************//
1010//  Check routine for all flag parameters
1011int MainWindow::check_flags()
1012{
1013
1014    int status = ui->check_delete_tmp_files->checkState();
1015
1016    if (status == 2)
1017    {
1018        activate_flag("B");
1019    }
1020    else
1021    {
1022        deactivate_flag("B");
1023    }
1024
1025    status = ui->check_verbose->checkState();
1026
1027    if (status == 2)
1028    {
1029        activate_flag("v");
1030    }
1031    else
1032    {
1033        deactivate_flag("v");
1034    }
1035
[818]1036    status = ui->check_namelist_check->checkState();
1037
1038    if (status == 2)
1039    {
1040        activate_flag("z");
1041    }
1042    else
1043    {
1044        deactivate_flag("z");
1045    }
1046
[793]1047    status = ui->check_A->checkState();
1048
1049    if (status == 2)
1050    {
1051        activate_flag("A");
1052    }
1053    else
1054    {
1055        deactivate_flag("A");
1056    }
1057
1058    status = ui->check_b->checkState();
1059
1060    if (status == 2)
1061    {
1062        activate_flag("b");
1063    }
1064    else
1065    {
1066        deactivate_flag("b");
1067    }
1068
1069    status = ui->check_F->checkState();
1070
1071    if (status == 2)
1072    {
1073        activate_flag("F");
1074    }
1075    else
1076    {
1077        deactivate_flag("F");
1078    }
1079    status = ui->check_I->checkState();
1080
1081    if (status == 2)
1082    {
1083        activate_flag("I");
1084    }
1085    else
1086    {
1087        deactivate_flag("I");
1088    }
1089    status = ui->check_k->checkState();
1090
1091    if (status == 2)
1092    {
1093        activate_flag("k");
1094    }
1095    else
1096    {
1097        deactivate_flag("k");
1098    }
1099    status = ui->check_O->checkState();
1100
1101    if (status == 2)
1102    {
1103        activate_flag("O");
1104    }
1105    else
1106    {
1107        deactivate_flag("O");
1108    }
1109    status = ui->check_S->checkState();
1110
1111    if (status == 2)
1112    {
1113        activate_flag("S");
1114    }
1115    else
1116    {
1117        deactivate_flag("S");
1118    }
1119    status = ui->check_x->checkState();
1120
1121    if (status == 2)
1122    {
1123        activate_flag("x");
1124    }
1125    else
1126    {
1127        deactivate_flag("x");
1128    }
[920]1129   
1130    status = ui->check_Z->checkState();
1131
1132    if (status == 2)
1133    {
1134        activate_flag("Z");
1135    }
1136    else
1137    {
1138        deactivate_flag("Z");
1139    }
[793]1140    return 0;
1141
1142}
1143
1144
1145//****************************************************************************//
1146//  Activate flag
1147int MainWindow::activate_flag(QString id)
1148{
1149    QString newmrunline;
1150
1151    QString mrunline = ui->commandline->text();
1152
1153    QStringList splitline = mrunline.split(" -"+id, QString::SkipEmptyParts);
1154    if ( splitline.count() == 1)
1155    {
1156        splitline.append("");
1157        newmrunline = splitline.join(" -"+id);
1158
1159 //     print new commandline to screen
1160        newmrunline.replace("  "," ");
1161        ui->commandline->setText(newmrunline);
1162
1163       return 0;
1164    }
1165    else
1166    {
1167       return 0;
1168    }
1169}
1170
1171
1172//****************************************************************************//
1173//  Deactivate flag
1174int MainWindow::deactivate_flag(QString id)
1175{
1176    QString newmrunline;
1177
1178    QString mrunline = ui->commandline->text();
1179
1180    QStringList splitline = mrunline.split(" -"+id, QString::SkipEmptyParts);
1181
1182    newmrunline = splitline.join("");
1183//  print new commandline to screen
1184    newmrunline.replace("  "," ");
1185    ui->commandline->setText(newmrunline);
1186
1187    return 0;
1188}
1189
1190
1191//****************************************************************************//
1192//  Mainwindow reset
1193int MainWindow::reset_window()
1194{
1195    ui->setupUi(this);
1196    recent_jobs(10);
1197    return 0;
1198}
1199
1200
1201//****************************************************************************//
1202//  Save current setting as default
1203int MainWindow::save_default()
1204{
1205
1206//  Get mrunline
1207    QString mrunline_save;
1208    QString mrunline = ui->commandline->text();
1209    QString userline = ui->line_user->text();
1210
1211    mrunline_save = mrunline;
1212    if (userline != "")
1213    {
1214        mrunline = mrunline + " " + userline;
1215    }
1216
1217
1218//  Define filename
1219    branch = QCoreApplication::applicationDirPath();
1220    branch = branch.left(branch.length() - 14);
1221
1222    QString filename = branch+"/.mrun.gui.default";
1223
1224//  Prepare data output
1225    QDateTime time = QDateTime::currentDateTime();
1226    QString tmptime = time.toString("yyyy/MM/dd hh:mm");
1227
1228//  Write to file
1229    QFile file(filename);
1230    file.open(QIODevice::WriteOnly | QIODevice::Text);
1231    QTextStream out(&file);
1232    if ( mrunline == "" || mrunline == " ")
1233    {
1234        out << "";
1235    }
1236    else
1237    {
1238       out << tmptime + " " + mrunline;
1239    }
1240
1241    file.close();
1242
1243    return 0;
1244}
1245
1246
1247//****************************************************************************//
1248//  Save current settings to a file of choice
1249int MainWindow::save_to_file()
1250{
1251
1252//  Get mrunline
1253    QString mrunline_save;
1254    QString mrunline = ui->commandline->text();
1255    QString userline = ui->line_user->text();
1256
1257    mrunline_save = mrunline;
1258    if (userline != "")
1259    {
1260        mrunline = mrunline + " " + userline;
1261    }
1262
1263//  Define a filename
1264    QString filename = QFileDialog::getSaveFileName(this, tr("Save to file"), \
1265                                    "", tr("Save files (*.sav)"));
1266    QString extension = filename.right(4);
1267
1268    if ( extension != ".sav" )
1269    {
1270        filename = filename + ".sav";
1271    }
1272
1273//  Prepare data output
1274    QDateTime time = QDateTime::currentDateTime();
1275    QString tmptime = time.toString("yyyy/MM/dd hh:mm");
1276
1277//  Write to file
1278    QFile file(filename);
1279    file.open(QIODevice::WriteOnly | QIODevice::Text);
1280    QTextStream out(&file);
1281    out << tmptime + " " + mrunline;
1282    file.close();
1283
1284    return 0;
1285}
1286
[1611]1287//****************************************************************************//
1288//  Start watchdog (palm_wd)
1289int MainWindow::start_watchdog()
1290{
1291    system("nohup palm_wd >> /dev/null 2>&1 &");
[793]1292
[1611]1293    return 0;
1294}
1295
1296
[793]1297//****************************************************************************//
1298//  Open job from file (previously saved by the user)
1299int MainWindow::open_from_file()
1300{
1301
1302//  Select filename and open it
1303    QString filename = QFileDialog::getOpenFileName(this, tr("Open File"), \
1304                                    "", tr("Save files (*.sav)"));
1305
1306    QFile file(filename);
1307    QString mrunline;
1308    if ( filename != "")
1309    {
1310       if ( file.open(QIODevice::ReadOnly | QIODevice::Text ) )
1311       {
1312
1313//        File opened successfully
1314          QTextStream in(&file);
1315
1316          QString line = in.readLine();
1317          while (!line.isNull())
1318          {
1319             mrunline = line;
1320             line = in.readLine();
1321          }
1322          file.close();
1323       }
1324
1325//     In case a mrunline was found, load it to mainwindow
1326       if ( mrunline != "")
1327       {
1328
1329          mrunline = mrunline.right(mrunline.length() - 17);
1330          ui->commandline->setText(mrunline);
1331
1332          setup_gui(mrunline);
1333       }
1334    }
1335    return 0;
1336}
1337
1338
1339//****************************************************************************//
1340//  Open the last submitted job
1341int MainWindow::open_last()
1342{
1343    branch = QCoreApplication::applicationDirPath();
1344    branch = branch.left(branch.length() - 14);
1345
1346    QFile file(branch+"/.mrun.history");
1347
1348//  Load mrun history
1349    QString mrunline;
1350    if ( file.open(QIODevice::ReadOnly | QIODevice::Text ) )
1351    {
1352
1353//     file opened successfully
1354       QTextStream in(&file);
1355
1356       QString line = in.readLine();
1357       while (!line.isNull())
1358       {
1359          mrunline = line;
1360          line = in.readLine();
1361       }
1362
1363       file.close();
1364    }
1365
1366//  Select the last submitted job and print it to mainwindow
1367    if ( mrunline != "" )
1368    {
1369       mrunline = mrunline.right(mrunline.length() - 17);
1370       ui->commandline->setText(mrunline);
1371
1372       setup_gui(mrunline);
1373    }
1374    return 0;
1375}
1376
1377//****************************************************************************//
1378//  Display help window
1379int MainWindow::help()
1380{
1381
1382    QDialog *child_help = new QDialog;
1383    Ui::child_help ui;
1384    ui.setupUi(child_help);
1385    child_help->show();
1386
1387
1388    return 0;
1389}
1390
1391//****************************************************************************//
1392//  Display about window
1393int MainWindow::about_gui()
1394{
1395
1396    QDialog *about = new QDialog;
1397    Ui::about ui;
1398    ui.setupUi(about);
1399    about->show();
1400
1401    return 0;
1402}
1403
1404//****************************************************************************//
1405//  Setup mainwindow according to a given mrunline
1406int MainWindow::setup_gui(QString mrunline)
1407{
1408
1409//  Some initial settings
1410    QString user = "";
1411
1412    bool coupled_run = false;
1413    bool ocean_run   = false;
1414    bool advanced    = false;
1415    bool nojob       = false;
1416    bool rc_manual   = false;
1417
1418//  Split parameters in mrunline
1419    QStringList splitline = mrunline.split(" -", QString::SkipEmptyParts);
1420
1421    if ( splitline[0] != "mrun")
1422    {
1423        return 1;
1424
1425    }
1426    else
1427    {
1428        ui->group_job->setEnabled(true);
1429
1430//      Loop for all parameters in mrunline
1431        for(int i=splitline.count()-1; i>=1; i--)
1432        {
1433
1434//          Determine parameter
1435            QStringList splitparameter = splitline[i].split(" ", \
1436                                                      QString::SkipEmptyParts);
1437
1438            QString parameter = splitparameter[0];
1439            splitparameter.removeFirst();
1440            QString options = splitparameter.join(" ");
1441            options = options.replace("\"","");
1442
1443//          Check for suitable switch
1444            if ( parameter == "d")
1445            {
1446               if ( options != "")
1447               {
1448                  ui->line_jobname->setText(options);
1449                  nojob = false;
1450               }
1451               else
1452               {
1453                  nojob = true;
1454               }
1455            }
1456            else if ( parameter == "h")
1457            {
1458               ui->line_host->setText(options);
1459            }
1460            else if ( parameter == "q")
1461            {
1462               ui->line_q->setText(options);
1463            }
1464            else if ( parameter == "K")
1465            {
1466               ui->line_branch->setText(options);
1467            }
1468            else if ( parameter == "u")
1469            {
1470               ui->line_account->setText(options);
1471            }
1472            else if ( parameter == "X")
1473            {
1474               ui->line_pe->setText(options);
1475            }
1476            else if ( parameter == "T")
1477            {
1478               ui->line_tpn->setText(options);
1479            }
1480            else if ( parameter == "t")
1481            {
1482               ui->line_time->setText(options);
1483            }
1484            else if ( parameter == "B")
1485            {
1486               ui->check_delete_tmp_files->setChecked(true);
1487            }
1488            else if ( parameter == "v")
1489            {
1490               ui->check_verbose->setChecked(true);
1491            }
[818]1492            else if ( parameter == "z")
1493            {
1494               ui->check_namelist_check->setChecked(true);
1495            }
[793]1496            else if ( parameter == "A")
1497            {
1498               ui->check_A->setChecked(true);
1499            }
1500            else if ( parameter == "b")
1501            {
1502               ui->check_b->setChecked(true);
1503               advanced = true;
1504            }
1505            else if ( parameter == "F")
1506            {
1507               ui->check_F->setChecked(true);
1508               advanced = true;
1509            }
1510            else if ( parameter == "I")
1511            {
1512               ui->check_I->setChecked(true);
1513               advanced = true;
1514            }
1515            else if ( parameter == "k")
1516            {
1517               ui->check_k->setChecked(true);
1518               advanced = true;
1519            }
1520            else if ( parameter == "O")
1521            {
1522               ui->check_O->setChecked(true);
1523               advanced = true;
1524            }
1525            else if ( parameter == "S")
1526            {
1527               ui->check_S->setChecked(true);
1528               advanced = true;
1529            }
1530            else if ( parameter == "x")
1531            {
1532               ui->check_x->setChecked(true);
1533               advanced = true;
1534            }
[920]1535            else if ( parameter == "Z")
1536            {
1537               ui->check_Z->setChecked(true);
1538               advanced = true;
1539            } 
[793]1540            else if ( parameter == "m")
1541            {
1542               ui->line_m->setText(options);
1543               advanced = true;
1544            }
1545            else if ( parameter == "M")
1546            {
1547               ui->line_M->setText(options);
1548               advanced = true;
1549            }
1550            else if ( parameter == "a")
1551            {
1552               ui->line_a->setText(options);
1553               advanced = true;
1554            }
1555            else if ( parameter == "D")
1556            {
1557               ui->line_D->setText(options);
1558               advanced = true;
1559            }
1560            else if ( parameter == "c")
1561            {
1562               ui->line_c->setText(options);
1563               advanced = true;
1564            }
1565            else if ( parameter == "p")
1566            {
1567               ui->line_p->setText(options);
1568               advanced = true;
1569            }
1570            else if ( parameter == "s")
1571            {
1572               ui->line_s->setText(options);
1573               advanced = true;
1574            }
1575            else if ( parameter == "i")
1576            {
1577               ui->line_i->setText(options);
1578               advanced = true;
1579               rc_manual = true;
1580            }
1581            else if ( parameter == "o")
1582            {
1583               ui->line_o->setText(options);
1584               advanced = true;
1585               rc_manual = true;
1586            }
1587            else if ( parameter == "w")
1588            {
1589               ui->line_w->setText(options);
1590               advanced = true;
1591            }
1592
1593//          Determine settings for coupled restart runs
1594            else if ( parameter == "Y")
1595            {
1596                QStringList optionssplit = options.split(" ", \
1597                                                   QString::SkipEmptyParts);
1598
1599                ui->line_PE_atmos->setEnabled(true);
1600                ui->line_PE_ocean->setEnabled(true);
1601                ui->label_coupled1->setEnabled(true);
1602                ui->label_coupled2->setEnabled(true);
1603                ui->label_coupled3->setEnabled(true);
1604                ui->label_coupling->setEnabled(true);
1605
1606                if (optionssplit.count() == 2)
1607                {
1608                   ui->line_PE_atmos->setText(optionssplit[0]);
1609                   ui->line_PE_ocean->setText(optionssplit[1]);
1610                }
1611                else
1612                {
1613                   ui->line_PE_atmos->setText("");
1614                   ui->line_PE_ocean->setText("");
1615                }
1616                coupled_run = true;
1617            }
1618            else if ( parameter == "n")
1619            {
1620                if ( options == "shared")
1621                {
1622                    ui->combo_n->setCurrentIndex(1);
1623                }
1624                else if ( options == "non_shared")
1625                {
1626                    ui->combo_n->setCurrentIndex(2);
1627                }
1628                else
1629                {
1630                    ui->combo_n->setCurrentIndex(0);
1631                }
1632            }
1633            else if ( parameter == "y")
1634            {
1635               ui->drop_job->setCurrentIndex(3);
1636            }
1637
1638//          Determine settings for the run control list
1639            else if ( parameter == "r")
1640            {
1641               QStringList optionssplit = options.split(" ", \
1642                                          QString::SkipEmptyParts);
1643
1644               QString options_2;
1645               QString options_all;
1646               for (int j=0; j<optionssplit.count(); j++)
1647               {
1648                   options_all = optionssplit[j];
1649                   options_2 = optionssplit[j].left(2);
1650                   if (options_2 == "ts")
1651                   {
1652                       ui->check_ts->setChecked(true);
1653                   }
1654                   if (options_2 == "pr" && options_all.left(3) != "prt")
1655                   {
1656                       ui->check_pr->setChecked(true);
1657                   }
1658                   if (options_2 == "xy")
1659                   {
1660                       ui->check_xy->setChecked(true);
1661                   }
1662                   if (options_2 == "xz")
1663                   {
1664                       ui->check_xz->setChecked(true);
1665                   }
1666                   if (options_2 == "yz")
1667                   {
1668                       ui->check_yz->setChecked(true);
1669                   }
1670                   if (options_2 == "3d")
1671                   {
1672                       ui->check_3d->setChecked(true);
1673                   }
1674                   if (options_2 == "ma")
1675                   {
1676                       ui->check_ma->setChecked(true);
1677                   }
1678                   if (options_2 == "sp")
1679                   {
1680                       ui->check_sp->setChecked(true);
1681                   }
1682                   if (options_all.left(3) == "prt")
1683                   {
1684                       ui->check_prt->setChecked(true);
1685                   }
1686                   if (options_all.left(3) == "pts")
1687                   {
1688                       ui->check_pts->setChecked(true);
1689                   }
1690                   if (options_2 == "d3")
1691                   {
1692                       if (options_all.left(3).right(1) == "#")
1693                       {
1694                          ui->drop_job->setCurrentIndex(0);
1695                       }
1696                       else if (options_all.left(3).right(1) == "f")
1697                       {
1698                          ui->drop_job->setCurrentIndex(1);
1699                       }
1700                       else if (options_all.left(3).right(1) == "o")
1701                       {
1702                          ocean_run = true;
1703                       }
1704                   }
1705                   if (options_all == "restart")
1706                   {
1707                      ui->check_restarts->setChecked(true);
1708//                    Check if _pdf file is available, otherwise notice user
1709                      QString jobname = ui->line_jobname->text();
1710                      branch = QCoreApplication::applicationDirPath();
1711                      branch = branch.left(branch.length() - 14);
1712
1713                      QFile restartfile(branch+"/JOBS/"+jobname+"/INPUT/"+ \
1714                                        jobname+"_p3df");
1715                      if (restartfile.exists() == true)
1716                      {
1717                         ui->label_restart->setText("");
1718                      }
1719                      else
1720                      {
1721                         ui->label_restart->setText("Warning: No p3df file \
1722                                                    found!");
1723                      }
1724                   }
1725
1726               }
1727
1728            }
1729
1730//          All unknown parameters are set as extra user parameters
1731            else
1732            {
1733                user = user + "-" + parameter + " \"" + options + "\" ";
1734                splitline.removeAt(i);
1735            }
1736        }
1737
1738//      Change drop box state in case of ocean precursor or coupled restart runs
1739        if ( ocean_run == true )
1740        {
1741           if ( coupled_run == true )
1742           {
1743             ui->drop_job->setCurrentIndex(4);
1744           }
1745           else
1746           {
1747              ui->drop_job->setCurrentIndex(3);
1748           }
1749        }
1750
1751        if ( user != "")
1752        {
1753           ui->line_user->setText(user);
1754        }
1755
1756//      Join mrunline and post it to mainwindow
1757        mrunline = splitline.join(" -");
1758        ui->commandline->setText(mrunline);
1759
1760//      Check if advanced settings are used and enable advanced dialog
1761        if ( advanced == true )
1762        {
1763           ui->check_advanced->setChecked(true);
1764        }
1765
1766//      Disable mainwindow if no job was found, otherwise enable
1767        if ( nojob == true )
1768        {
1769           ui->group_execution->setEnabled(false);
1770           ui->group_runcontrol->setEnabled(false);
1771           ui->button_start->setEnabled(false);
1772           ui->action_save->setEnabled(false);
1773           ui->drop_job->setEnabled(false);
1774           ui->group_advanced->setEnabled(false);
1775           ui->check_advanced->setEnabled(false);
1776        }
1777        else
1778        {
1779           ui->group_execution->setEnabled(true);
1780           ui->group_runcontrol->setEnabled(true);
1781           ui->button_start->setEnabled(true);
1782           ui->action_save->setEnabled(true);
1783           ui->check_advanced->setEnabled(true);
1784           ui->drop_job->setEnabled(true);
1785           if ( advanced == true )
1786           {
1787              ui->group_advanced->setEnabled(true);
1788           }
1789           else
1790           {
1791              ui->group_advanced->setEnabled(false);
1792           }
1793        }
1794
1795//      Disable run control box, if manual settings of -i and -o are used
1796        if ( rc_manual == true )
1797        {
1798           ui->group_runcontrol->setEnabled(false);
1799           change_commandline("r","remove");
1800           ui->button_start->setEnabled(true);
1801           ui->action_save->setEnabled(true);
1802        }
1803
1804    }
1805
1806    return 0;
1807}
Note: See TracBrowser for help on using the repository browser.