source: palm/trunk/SCRIPTS/palmrungui @ 4570

Last change on this file since 4570 was 4482, checked in by maronga, 5 years ago

added functionality to create new jobs and delete multiple files in palmrungui

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 69.0 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#--------------------------------------------------------------------------------#
4# This file is part of the PALM model system.
5#
6# PALM is free software: you can redistribute it and/or modify it under the terms
7# of the GNU General Public License as published by the Free Software Foundation,
8# either version 3 of the License, or (at your option) any later version.
9#
10# PALM is distributed in the hope that it will be useful, but WITHOUT ANY
11# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along with
15# PALM. If not, see <http://www.gnu.org/licenses/>.
16#
17# Copyright 1997-2020  Leibniz Universitaet Hannover
18#--------------------------------------------------------------------------------#
19#
20# Current revisions:
21# -----------------
22#
23#
24# Former revisions:
25# -----------------
26# $Id: palmrungui 4482 2020-04-01 13:17:50Z gronemeier $
27# Added possibility to delete all files in a directory and option to create
28# blank new jobs
29#
30# 4481 2020-03-31 18:55:54Z maronga
31# Bugfixes: - reading history lines discard button caused error message
32#           - deleting of USER_CODE files did not work
33#
34# 4470 2020-03-24 06:52:19Z maronga
35# Added file size output, more I/O functionalities, new/removed buttons
36#
37# 4428 2020-02-27 11:43:53Z maronga
38# Bugfix for update button
39#
40# 4427 2020-02-27 11:29:51Z maronga
41# Small fixes and adjustments
42#
43# 4420 2020-02-24 14:13:56Z maronga
44# Bugfix: minor fixes related to start buttons
45#
46# 4411 2020-02-18 14:28:02Z maronga
47# Added new features: individual tag for submitted runs, automatic finding of
48# configuration, start of palmbuild from GUI
49#
50# 4405 2020-02-12 19:11:11Z maronga
51# Major revisions: New layout. Merged with palm job manager (palm_jm).
52# Minor revisions: Misc. bugs fixed.
53#
54# 4394 2020-02-04 21:40:38Z maronga
55# Bugfix: harmonized naming convention of configuration files
56#
57# 4393 2020-02-04 21:24:48Z maronga
58# Removed PALM_BIN dependency and os calls
59#
60# 3487 2018-11-05 07:18:02Z maronga
61# Renamed options -d and -h to -r and -c.
62#
63# 2825 2018-02-20 21:48:27Z maronga
64# Adjusted to work with newest version of palmrun
65#
66# 2718 2018-01-02 08:49:38Z maronga
67# Corrected "Former revisions" section
68#
69# 2696 2017-12-14 17:12:51Z kanani
70# Change in file header (GPL part)
71#
72# 2484 2017-09-20 14:22:42Z maronga
73# Added PALM logo
74#
75# 2480 2017-09-19 06:24:14Z maronga
76# option -A (project account number) added
77#
78# 2477 2017-09-18 08:42:29Z maronga
79# Renamed restart run appendix from "f" to "r". Bugfix for displaying restart runs.>
80# Revised list of recently submitted jobs
81#
82# 2413 2017-09-06 12:48:29Z maronga
83# Renamed to palmrungui and adapted for use with palmrun instead of mrun.
84#
85# 2316 2017-07-20 07:53:42Z maronga
86# Initial revision in python
87#
88#
89#
90# Description:
91# ------------
92# Graphical user interface for the palmrun script.
93# @author Felix Gaschler
94# @author Björn Maronga (maronga@muk.uni-hannover.de)
95#
96# Instructions:
97# -------------
98#
99#------------------------------------------------------------------------------!
100
101import sys
102import subprocess
103from PyQt4 import QtCore, QtGui, uic
104from PyQt4.QtCore import QProcess,pyqtSlot,SIGNAL,SLOT
105from time import strftime
106import os
107import shutil
108
109global update_frequency
110update_frequency = 5*60000
111
112# Determine PALM directories
113try: 
114   devnull = open(os.devnull, 'w')     
115   palm_dir = os.getcwd()
116   palm_bin = palm_dir + '/trunk/SCRIPTS'
117   palm_source = palm_dir + '/trunk/SOURCE'
118   job_dir = palm_dir + '/JOBS'
119   user_dir = palm_dir + '/USER_CODE'
120   with open(palm_bin + '/palmrungui', 'r') as fh:
121      # file found
122      out = None
123except:   
124   print "Error. palmrungui probably called in wrong directory."
125   raise SystemExit
126
127
128# returns the human readable file size of filename
129def file_size(filename, suffix='B'):
130   size_raw = os.stat(filename).st_size
131   for unit in [' ',' K',' M',' G',' T']:
132      if abs(size_raw) < 1024.0:
133         return "%i%s%s" % (size_raw, unit, suffix)
134      size_raw /= 1024.0
135   return "%.1f%s%s" % (num, 'Y', suffix)
136
137
138
139palmrunline = ""
140set_list = []
141
142Ui_MainWindow = uic.loadUiType("%s/palmrungui_files/mainwindow.ui" % (palm_bin))[0]
143Ui_helpDialog = uic.loadUiType("%s/palmrungui_files/help.ui" % (palm_bin))[0]
144Ui_aboutDialog = uic.loadUiType("%s/palmrungui_files/about.ui" % (palm_bin))[0]
145
146class HelpDialog(QtGui.QDialog,Ui_helpDialog):
147    def __init__(self, parent=None):
148        super(HelpDialog,self).__init__()
149        self.setupUi(self)
150       
151class AboutDialog(QtGui.QDialog,Ui_aboutDialog):
152    def __init__(self, parent=None):
153        super(AboutDialog,self).__init__()
154        self.setupUi(self)       
155
156class Mainwindow(QtGui.QMainWindow, Ui_MainWindow):
157    def __init__(self, parent=None):
158        super(Mainwindow, self).__init__()
159        self.setupUi(self)
160   
161        self.palm_logo.setPixmap(QtGui.QPixmap(palm_bin + "/palmrungui_files/logo.png"))       
162       
163        with open(palm_bin + "/palmrungui") as search:
164           for line in search:
165              line = line.rstrip()
166              if "$Id" in line:
167                 version = "Version: r" + line.split(" ")[3] + " (" + line.split(" ")[4] + ")"
168                 self.groupBox.findChild(QtGui.QLabel,"label_version").setText(version)
169                 break
170       
171        self.recent_jobs(50)
172        self.load_jobs()
173
174        # look up configuration files and add to combo box
175       
176        self.group_execution.findChild(QtGui.QComboBox,"combo_configuration").addItem("")
177       
178        for files in os.listdir(palm_dir):
179           if files.startswith(".palm.config"):
180              tmpstring = filter(None,files.split(".palm.config."))[0]
181              self.group_execution.findChild(QtGui.QComboBox,"combo_configuration").addItem(tmpstring)
182
183        commandline = self.groupBox.findChild(QtGui.QLineEdit,"commandline")
184        commandline.setText("")
185       
186        self.tabWidget.setCurrentIndex(0) 
187       
188       
189        filename = "%s/.palmrungui.default" % (palm_dir) 
190        if os.path.exists(filename):
191            pass
192        else:
193            return
194       
195        file = open(filename, "r")
196        if ( file is not None ):
197            # File opened successfully
198            palmrunline = file.readline()
199            #if neue zeile zeichen
200            palmrunline = palmrunline[:len(palmrunline)-1]
201            file.close() 
202
203        # In case a palmrunline was found, load it to mainwindow
204        if ( palmrunline != ""):
205            palmrunline = palmrunline[17:] 
206            commandline.setText(palmrunline)
207            self.setup_gui(palmrunline)
208
209
210        QtGui.QApplication.processEvents()
211
212
213        # Start refresh timer. On timeout perform update
214        self.timer = QtCore.QTimer(self)
215        self.timer.timeout.connect(self.update_all)
216        self.timer.setSingleShot(False)
217        self.timer.start(update_frequency)
218
219        # The timetimer counts the time since last update
220        self.timetimer= QtCore.QElapsedTimer()
221        self.timetimer.start()
222
223        # The labeltimer induces the update of the remaining time in the UI
224        self.labeltimer = QtCore.QTimer(self)
225        self.labeltimer.timeout.connect(self.UpdatePush)
226        self.labeltimer.setSingleShot(False)
227
228        # Update in the UI will be performed at each 1/10 of the update interval
229        self.labeltimer.start(update_frequency/10)
230        self.push_update.setText("Update (" + str(int(update_frequency/1000/60)) + " min)")
231
232    # starts xterm with palmrun commandline
233    #######################################
234    def startpalmrun(self):
235        palmrunline = str(self.groupBox.findChild(QtGui.QLineEdit,"commandline").text())
236        userline    = str(self.group_advanced.findChild(QtGui.QLineEdit,"line_user").text())
237       
238        # Check for empty line
239        palmrunline_save = palmrunline
240        if (userline != ""):
241            palmrunline = "%s %s" % (palmrunline,userline)
242        history_line = palmrunline       
243       
244        # Disable the main window
245        self.tabWidget.setEnabled(False)
246        self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(False)
247        self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(False)
248        self.groupBox.findChild(QtGui.QPushButton,"button_start").setText("wait...")     
249        self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText("Executing palmrun in xterm...")       
250
251        # Wait until all commands have been executed (ugly) ?
252        #for i in range(0,21):
253        #    qApp->processEvents()       
254
255        # Start xterm as QProcess
256        palmrun = QProcess()
257        palmrun.setProcessChannelMode(QProcess.MergedChannels) # mergedChannels
258        palmrun.setWorkingDirectory(palm_dir)
259
260        geomet = self.frameGeometry()
261
262        posx = geomet.x()+geomet.width()
263        posy = geomet.y()
264
265        if ( os.path.isfile("palmrungui.log") ):
266           os.remove("palmrungui.log")
267
268        s = " -title \"Executing palmrun...\" -fa \"Monospace\" -l -lf \"palmrungui.log\" -fs 11 -geometry \"80x38+%d+%d\" -e \"" % (posx,posy)
269        palmrunline = "%s%s ;echo -n '--> Press enter to continue...';read yesno\"</dev/stdin" % (s, palmrunline.replace("\"","\'"))
270
271        mString = "xterm %s" % (palmrunline)
272        palmrun.start(mString)
273
274        if( palmrun.waitForStarted() is False ):
275            return
276
277        # Wait until palmrun has finished or wait for 200 minutes
278        palmrun.waitForFinished(3600000)       
279
280        # Jobs has been submitted or aborted. Continuing...
281        # Save the palmrun command to history file
282        filename = "%s/.palmrungui.history" % (palm_dir)
283        tmstamp = strftime("%Y/%m/%d %H:%M")
284        tag = str(self.groupBox.findChild(QtGui.QLineEdit,"line_tag").text())
285   
286        file = open(filename,"a")
287        s = "%s %s (%s)\n" % (tmstamp,history_line,tag)
288        file.write(s)
289        file.close()             
290       
291        # Enable main window again
292        self.tabWidget.setEnabled(True)
293        self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(True)
294        self.groupBox.findChild(QtGui.QPushButton,"button_start").setText("palmrun") 
295        self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText(palmrunline_save)
296        self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(True)
297       
298        # Reload recent jobs
299        self.recent_jobs(50)
300       
301       
302       
303    # Update the label
304    def UpdatePush(self):
305        remaining_time = (update_frequency - self.timetimer.elapsed()) / 1000 / 60
306        self.push_update.setText("Update (" + str(remaining_time) + " min)")
307
308
309    # starts xterm with palmbuild commandline
310    #######################################
311    def startpalmbuild(self):
312        palmbuildline = 'palmbuild -c ' + str(self.group_execution.findChild(QtGui.QComboBox, "combo_configuration").currentText())
313
314        full_build = self.group_execution.findChild(QtGui.QCheckBox,"check_rebuild").checkState()
315
316        if ( full_build == 2 ):
317           for filename in os.listdir(palm_source):
318              os.utime(palm_source + "/" + filename, None)
319
320        palmrunline_save = str(self.groupBox.findChild(QtGui.QLineEdit,"commandline").text())
321
322        # Disable the main window
323        palmbuildline_save = palmbuildline
324        self.tabWidget.setEnabled(False)
325        self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(False)
326        self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(False) 
327        self.groupBox.findChild(QtGui.QPushButton,"button_start").setText("wait...") 
328        self.group_execution.findChild(QtGui.QPushButton,"button_palmbuild").setText("wait...") 
329        self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText("Executing palmbuild in xterm...")       
330       
331        # Wait until all commands have been executed (ugly) ?
332        #for i in range(0,21):
333        #    qApp->processEvents()       
334       
335        # Start xterm as QProcess
336        palmbuild = QProcess()
337        palmbuild.setProcessChannelMode(QProcess.MergedChannels) # mergedChannels
338        palmbuild.setWorkingDirectory(palm_dir)
339   
340        geomet = self.frameGeometry()
341       
342        posx = geomet.x()+geomet.width()
343        posy = geomet.y()
344     
345        s = " -title \"Executing palmbuild...\" -fa \"Monospace\" -fs 11 -geometry \"80x38+%d+%d\" -e \"" % (posx,posy)
346        palmbuildline = "%s%s;echo -n '--> Press enter to continue...';read yesno\"</dev/stdin" % (s, palmbuildline.replace("\"","\'"))
347       
348        mString = "xterm %s" % (palmbuildline)
349        palmbuild.start(mString)
350   
351        if( palmbuild.waitForStarted() is False ):
352            return
353       
354        # Wait until palmbuild has finished or wait for 200 minutes
355        palmbuild.waitForFinished(3600000)       
356       
357         
358       
359        # Enable main window again
360        self.tabWidget.setEnabled(True)
361        self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(True)
362        self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(True)
363        self.groupBox.findChild(QtGui.QPushButton,"button_start").setText("palmrun") 
364        self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText(palmrunline_save)
365        self.group_execution.findChild(QtGui.QPushButton,"button_palmbuild").setText("(re-)build")     
366        # Reload recent jobs
367        self.recent_jobs(50)
368
369    # loads recent jobs
370    ######################################
371    def recent_jobs(self, number):
372        fileDir = "%s/.palmrungui.history" % (palm_dir)
373        if os.path.exists(fileDir):
374            pass
375        else:
376            return
377
378        file = open(fileDir,"r")
379        history = file.readlines()
380        tmphistory = list()
381        tmptag = list()
382        file.close()
383        j = 0
384
385        list_jobname = self.group_history.findChild(QtGui.QListWidget,"list_jobname")
386        list_jobname.clear()
387
388        # Read history entries and append to recent job list
389        i=len(history)-1
390        count = 0
391        while i>=0 and count<number:
392            timestamp = history[i][:16]
393            listitem = history[i][17:len(history[i])-1]
394            tagitem = listitem
395            configitem = listitem
396            matchitems = list_jobname.findItems(listitem, QtCore.Qt.MatchExactly)
397
398            if ( len(matchitems) == 0 ):
399                listitem = filter(None,listitem.split(" -r"))[1]
400                listitem = listitem.strip()
401                listitem = filter(None,listitem.split(" "))[0]
402                listitem = listitem.replace("\"","") 
403                list_jobname.addItem(listitem)
404               
405                configitem = filter(None,configitem.split(" -c"))[1]
406                configitem = configitem.strip()
407                configitem = filter(None,configitem.split(" "))[0]
408                configitem = configitem.replace("\"","") 
409
410                s = "%s: %s (%s)" % (timestamp,listitem,configitem)
411                tmphistory.append(s)
412               
413               
414                tagitem = filter(None,tagitem.split(" ("))[1]
415                tagitem = tagitem.replace(")","") 
416                if ( len(tagitem) == 0 ): 
417                   s = "Tag: empty"
418                else:
419                   s = "Tag: %s" % (tagitem)               
420                tmptag.append(s)
421                count = count +1
422
423                j = j+1
424               
425            if ( j == number ):
426                break
427            i = i-1
428           
429        # Send to list
430        list_jobname.clear()
431       
432        i=0
433        while i<len(tmphistory):
434            list_jobname.addItem(tmphistory[i])
435            list_jobname.item(i).setToolTip(tmptag[i])
436            i = i+1
437           
438
439    # Enables coupled settings
440    ###############################
441    def enable_coupled(self):
442        coupledState = self.group_execution.findChild(QtGui.QComboBox, "drop_job").currentText()
443        group = self.group_execution.findChild(QtGui.QGroupBox, "group_coupled")
444       
445        if (coupledState == "Restart run (coupled atmosphere ocean)" or coupledState == "Initial run (coupled atmosphere ocean)"):
446            self.group_coupled.setEnabled(True)
447        else: 
448            self.group_coupled.setEnabled(False)
449           
450
451    # select a job via click from list
452    #################################
453    def choosejob_list(self):
454        #  Get selected item from list
455        list_jobname = self.group_history.findChild(QtGui.QListWidget,"list_jobname")
456        filename = str(list_jobname.currentItem().text())
457
458        timestamp = filename[:16]
459        jobname = filename[18:].split(" ")[0]
460
461        itemint = list_jobname.currentRow()
462
463        # Reload list
464        self.recent_jobs(50)
465        self.load_jobs()
466   
467        # Set selected item to jobname
468        list_jobname.item(itemint).setSelected(True)
469   
470        # Set selected item to jobname in "available jobs" list
471        item2int = self.list_jobs.findItems(jobname,QtCore.Qt.MatchCaseSensitive)
472       
473        if ( item2int != [] ):
474           self.list_jobs.setCurrentItem(item2int[0])
475        self.update_input()
476           
477   
478        fileDir = "%s/.palmrungui.history" % (palm_dir)
479        file = open(fileDir,"r")
480        history = file.readlines()
481        tmphistory = list()
482        file.close()       
483   
484        i = len(history)
485        while i>=1:
486            listitem = history[i-1][17:len(history[i-1])-1]
487            listitem = filter(None,listitem.split(" -r"))[1]
488            listitem = listitem.strip()
489            listitem = filter(None,listitem.split(" "))[0]
490            listitem = listitem.replace("\"","") 
491
492            # Select command line with correct timestamp and jobname
493            if (history[i-1][:16] == timestamp and listitem == jobname):
494                palmrunline = history[i-1]
495                palmrunline = palmrunline[17:]
496                palmrunline = palmrunline[:len(palmrunline)-1]
497                palmrunline = filter(None,palmrunline.split("("))[0]
498                self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText(palmrunline)
499               
500             
501                tag = history[i-1].split('\n')[0]
502                tag = filter(None,tag.split("("))[1]
503                tag = tag.replace(")","")
504
505                self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setText(tag)
506                self.setup_gui(palmrunline)
507                self.list_jobname.item(itemint).setSelected(True)   
508               
509                return
510            i = i-1
511               
512    # Change run identifer (initial, restart, coupled...)
513    ######################################################
514    def change_rc_list(self):
515        drop_job = self.group_execution.findChild(QtGui.QComboBox,"drop_job").currentText()   
516        self.change_commandline("a","")
517   
518        # Enable PE distribution for atmosphere/ocean
519        if ( drop_job == "Restart run (coupled atmosphere ocean)" or drop_job == "Initial run (coupled atmosphere ocean)"):
520            drop_atmos = self.group_coupled.findChild(QtGui.QLineEdit,"line_PE_atmos").text() 
521            drop_ocean = self.group_coupled.findChild(QtGui.QLineEdit,"line_PE_ocean").text() 
522            s = "%s %s" % (drop_atmos,drop_ocean)
523            self.change_commandline("Y",s)
524   
525   
526        if ( drop_job == "Restart run" or drop_job == "Restart run (coupled atmosphere ocean)"):
527           self.change_commandline("r","")
528
529        # Check of ocean runs
530        else:
531            self.delete_commandline("Y")
532            if (drop_job == "Precursor run (ocean)"):
533                self.activate_flag("y")
534            else:
535                self.deactivate_flag("y")
536           
537    # changes commandline depending on parameters
538    ##########################################################     
539    def change_commandline(self, id_str, fwt_str):
540        fwt_str = str(fwt_str) 
541        initialize = False
542        palmrunline = str(self.groupBox.findChild(QtGui.QLineEdit,"commandline").text())   
543        s = " -%s " % (id_str)
544        splitline = filter(None,palmrunline.split(s))
545
546        if ( len(splitline) == 0 ):
547                splitline.append("palmrun")
548                splitline.append(" ")
549                initialize = True
550
551        elif ( len(splitline) == 1 ):
552            splitline.append(" ")
553       
554        param = splitline[1].split("-")
555   
556        # Change in parameter "r" (jobname)
557        if (id_str == "r"):
558            filename = str(self.group_execution.findChild(QtGui.QLineEdit,"line_jobname").text())
559            s = filename.split("JOBS/") 
560            param[0] = s[len(s)-1]
561     
562            if ( initialize == True ):#and self.group_runcontrol.isEnabled() == True ):
563                self.group_execution.setEnabled(True)
564                self.group_execution.findChild(QtGui.QComboBox,"drop_job").setEnabled(True)
565                self.group_advanced.setEnabled(True)
566                self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(True) 
567                self.menuBar.findChild(QtGui.QMenu,"menuStart").actions()[3].setEnabled(True)
568                self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(True)
569           
570            elif ( param[0] == ""):           
571                self.group_execution.setEnabled(False)
572                self.group_execution.findChild(QtGui.QComboBox,"drop_job").setEnabled(False)
573                self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(False) 
574                self.menuBar.findChild(QtGui.QMenu,"menuStart").actions()[3].setEnabled(False)
575                self.group_advanced.setEnabled(False)
576                self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(True)
577                self.delete_commandline("r")
578                self.change_commandline("a","remove")
579                return 1 
580           
581            else:
582
583                self.group_execution.setEnabled(True)
584                self.drop_job.setEnabled(True)
585                self.group_advanced.setEnabled(True)
586                   
587        # Change in parameter "a" (run control list)
588        elif (id_str == "a"): 
589   
590            drop_job = self.group_execution.findChild(QtGui.QComboBox,"drop_job").currentText()
591            rc_flag = "#"
592   
593            if (drop_job == "Initial run"):
594                rc_flag = "#"
595           
596            elif (drop_job == "Restart run"):           
597                rc_flag = "r"
598           
599            elif (drop_job == "Precursor run (atmosphere)"):           
600                rc_flag = "#"
601           
602            elif (drop_job == "Precursor run (ocean)"):           
603                rc_flag = "o#"
604
605            elif (drop_job == "Initial run (coupled atmosphere ocean)"):           
606                rc_flag = "#"
607           
608            elif (drop_job == "Restart run (coupled atmosphere ocean)"):           
609                rc_flag = "r"
610           
611            param[0] = "\"d3%s" % (rc_flag)
612   
613   
614            if (drop_job == "Restart run (coupled atmosphere ocean)" or drop_job == "Initial run (coupled atmosphere ocean)"):
615                if (rc_flag == "#"):
616                   rc_flag = "o#"
617                else:
618                   rc_flag = "or"
619
620                param[0] = "%s d3%s" % (param[0],rc_flag)
621   
622            status_restarts = self.group_execution.findChild(QtGui.QCheckBox,"check_restarts").checkState()
623
624            if (status_restarts == 2):
625                param[0]="%s restart" % (param[0])
626
627
628            status_cycfill = self.group_execution.findChild(QtGui.QCheckBox,"check_cycfill").checkState()
629   
630            if (status_cycfill == 2):           
631                param[0]="%s fill" % (param[0])
632           
633            status_svf = self.group_execution.findChild(QtGui.QCheckBox,"check_svf").checkState()
634   
635            if (status_svf == 2):           
636                param[0]="%s svf" % (param[0])
637
638            param[0]="%s\"" % (param[0])
639 
640 
641            if ( fwt_str == "remove"):           
642                self.delete_commandline(id_str)
643                return 1
644           
645            else:           
646                self.button_start.setEnabled(True)
647                self.action_save.setEnabled(True)
648                self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(True)
649
650        # Change in any other parameter
651        else:
652            if ( fwt_str != ""):           
653                param[0] = "\"%s\"" % (fwt_str)
654           
655            else:           
656                self.delete_commandline(id_str)
657                return 1
658                       
659        # Join the new palmrunline
660        splitline[1]= " -".join(param)
661               
662               
663        s = " -%s " % (id_str)
664        newpalmrunline = s.join(splitline)
665   
666        # Pr the new palmrunline to mainwindow
667        newpalmrunline = newpalmrunline.replace("  "," ")
668        self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText(newpalmrunline)
669
670    # change lineinput depending on sender
671    ###################################################################################
672    def change_lineinput(self):
673        if ( self.sender() == self.group_execution.findChild(QtGui.QComboBox, "combo_configuration") ):
674            tmptext = self.group_execution.findChild(QtGui.QComboBox, "combo_configuration").currentText()
675            if tmptext.isEmpty():
676               self.change_commandline("c"," ")
677               self.group_execution.findChild(QtGui.QPushButton,'button_palmbuild').setEnabled(False)
678            else:
679               self.change_commandline("c",tmptext)
680               self.group_execution.findChild(QtGui.QPushButton,'button_palmbuild').setEnabled(True)         
681
682        elif ( self.sender() == self.group_execution.findChild(QtGui.QLineEdit,"line_q")):
683            tmptext = self.group_execution.findChild(QtGui.QLineEdit,"line_q").text()
684            self.change_commandline("q",tmptext)
685       
686        elif ( self.sender() == self.group_execution.findChild(QtGui.QLineEdit,"line_account")):
687            tmptext = self.group_execution.findChild(QtGui.QLineEdit,"line_account").text()
688            self.change_commandline("A",tmptext)
689       
690        elif ( self.sender() ==  self.group_execution.findChild(QtGui.QLineEdit,"line_pe")):
691            tmptext = self.group_execution.findChild(QtGui.QLineEdit,"line_pe").text()
692            self.change_commandline("X",tmptext)
693       
694        elif ( self.sender() == self.group_execution.findChild(QtGui.QLineEdit,"line_tpn")):
695            tmptext = self.group_execution.findChild(QtGui.QLineEdit,"line_tpn").text()
696            self.change_commandline("T",tmptext)
697               
698        elif ( self.sender() == self.group_execution.findChild(QtGui.QLineEdit,"line_time")):
699            tmptext = self.group_execution.findChild(QtGui.QLineEdit,"line_time").text()
700            self.change_commandline("t",tmptext)
701       
702        elif ( self.sender() == self.group_advanced.findChild(QtGui.QLineEdit,"line_M")):
703            tmptext = self.group_advanced.findChild(QtGui.QLineEdit,"line_M").text()
704            self.change_commandline("M",tmptext)
705       
706        elif ( self.sender() == self.group_advanced.findChild(QtGui.QLineEdit,"line_m")):
707            tmptext = self.group_advanced.findChild(QtGui.QLineEdit,"line_m").text()
708            self.change_commandline("m",tmptext)
709       
710        elif ( self.sender() == self.group_advanced.findChild(QtGui.QLineEdit,"line_D")):
711            tmptext = self.group_advanced.findChild(QtGui.QLineEdit,"line_D").text()
712            self.change_commandline("D",tmptext)
713       
714        elif ( self.sender() == self.group_advanced.findChild(QtGui.QLineEdit,"line_c")):
715            tmptext = self.group_advanced.findChild(QtGui.QLineEdit,"line_c").text()
716            if ( tmptext == ".palmrungui.config"):
717                tmptext = ""
718            self.change_commandline("c",tmptext)
719       
720        elif ( self.sender() == self.group_advanced.findChild(QtGui.QLineEdit,"line_s")):
721            tmptext = self.group_advanced.findChild(QtGui.QLineEdit,"line_s").text()
722            self.change_commandline("s",tmptext)
723               
724        elif ( self.sender() == self.group_advanced.findChild(QtGui.QLineEdit,"line_w")):
725            tmptext = self.group_advanced.findChild(QtGui.QLineEdit,"line_w").text()
726            self.change_commandline("w",tmptext)
727       
728        elif ( self.sender() == self.group_coupled.findChild(QtGui.QLineEdit,"line_PE_atmos") or 
729               self.sender() == self.group_coupled.findChild(QtGui.QLineEdit,"line_PE_ocean")):
730            t1 = self.group_coupled.findChild(QtGui.QLineEdit,"line_PE_atmos").text()
731            t2 = self.group_coupled.findChild(QtGui.QLineEdit,"line_PE_ocean").text()           
732            tmptext = "%s %s" % (t1,t2)
733           
734            self.change_commandline("Y",tmptext)
735
736            # try catch sowas in der art
737            pe1 = 0
738            pe2 = 0
739           
740            try:
741                pe1 = int(t1)
742            except ValueError:           
743                pass
744               
745            try:
746                pe2 = int(t2)
747            except ValueError:
748                pass
749               
750            PE_total = pe1+pe2   
751            self.group_execution.findChild(QtGui.QLineEdit,"line_pe").setText(str(PE_total))
752            self.change_commandline("X",str(PE_total))
753         
754    # deletes parameter from commandline
755    #####################################################################################
756    def delete_commandline(self, id_str):   
757        # Read palmrunline
758        commandline = self.groupBox.findChild(QtGui.QLineEdit,"commandline")
759        palmrunline = str(commandline.text())
760        s = " -%s" % (id_str)
761        splitline = filter(None,palmrunline.split(s))
762       
763        if ( len(splitline) == 1):
764            return 1
765        else:
766            param = splitline[1].split("-")
767            param[0] = ""
768            splitline[1]= " -".join(param)
769            newpalmrunline = "".join(splitline)
770            newpalmrunline = newpalmrunline.replace("  "," ")
771   
772            # Print new palmrunline to screen
773            commandline.setText(newpalmrunline)
774       
775    # controls flags
776    ###################################################################################
777    def check_flags(self):
778        status = self.group_execution.findChild(QtGui.QCheckBox,"check_delete_tmp_files" ).checkState()
779        if (status == 2):     
780            self.activate_flag("B")
781        else:
782            self.deactivate_flag("B")
783   
784        status = self.group_execution.findChild(QtGui.QCheckBox,"check_verbose" ).checkState()
785        if (status == 2):
786            self.activate_flag("v") 
787        else:
788            self.deactivate_flag("v")
789       
790        status = self.group_advanced.findChild(QtGui.QCheckBox,"check_b" ).checkState() 
791        if (status == 2):
792            self.activate_flag("b")
793        else:
794            self.deactivate_flag("b")
795   
796        status = self.group_advanced.findChild(QtGui.QCheckBox,"check_F" ).checkState()   
797        if (status == 2):
798            self.activate_flag("F")
799        else:
800            self.deactivate_flag("F")
801           
802        status = self.group_advanced.findChild(QtGui.QCheckBox,"check_I" ).checkState() 
803        if (status == 2):
804            self.activate_flag("I")
805        else:
806            self.deactivate_flag("I")
807
808        status = self.group_advanced.findChild(QtGui.QCheckBox,"check_k" ).checkState() 
809        if (status == 2):
810            self.activate_flag("k")
811        else:
812            self.deactivate_flag("k")
813
814        status = self.group_advanced.findChild(QtGui.QCheckBox,"check_O" ).checkState() 
815        if (status == 2):
816            self.activate_flag("O")
817        else:
818            self.deactivate_flag("O")
819
820        status = self.group_advanced.findChild(QtGui.QCheckBox,"check_x" ).checkState() 
821        if (status == 2):
822            self.activate_flag("x")
823        else:
824            self.deactivate_flag("x")
825       
826        status = self.group_advanced.findChild(QtGui.QCheckBox,"check_Z" ).checkState() 
827        if (status == 2):
828            self.activate_flag("Z")
829        else:
830            self.deactivate_flag("Z")
831       
832    # changes flag to parameter
833    ##################################################################################   
834    def activate_flag(self, id_str):
835        commandline = self.groupBox.findChild(QtGui.QLineEdit,"commandline")
836        palmrunline = str(commandline.text())
837        s = " -%s" % (id_str)
838        splitline = filter(None,palmrunline.split(s))
839       
840        if ( len(splitline) == 1):
841            splitline.append("")
842            s = " -%s" % (id_str)
843            newpalmrunline = s.join(splitline)
844            newpalmrunline = newpalmrunline.replace("  "," ")
845            commandline.setText(newpalmrunline)               
846       
847    # deletes flag in commandline
848    ####################################################################################   
849    def deactivate_flag(self, id_str):
850        commandline = self.groupBox.findChild(QtGui.QLineEdit,"commandline")
851        palmrunline = str(commandline.text())
852        s = " -%s" % (id_str)
853        splitline = filter(None,palmrunline.split(s))
854 
855        newpalmrunline = "".join(splitline)
856        newpalmrunline = newpalmrunline.replace("  "," ")
857        commandline.setText(newpalmrunline)     
858
859    # Clears window
860    #################################################################################
861    def reset_window(self):
862        self.setupUi(self)
863        self.tabWidget.setCurrentIndex(0)
864        self.palm_logo.setPixmap(QtGui.QPixmap(palm_dir + "/trunk/SCRIPTS/palmrungui_files/logo.png"))   
865        self.recent_jobs(50)
866        self.load_jobs()
867       
868
869    # Safes current commandline and user parameters to default file
870    ################################################################################
871    def save_default(self):
872        user_string = self.group_advanced.findChild(QtGui.QLineEdit,"line_user").text()
873        cmd_string = self.groupBox.findChild(QtGui.QLineEdit,"commandline").text()
874       
875        string_to_file = cmd_string
876        if (user_string != ""): 
877            string_to_file = "%s%s" % (string_to_file,user_string)
878       
879        filename ="%s/.palmrungui.default" % (palm_dir)
880        tmstamp = strftime("%Y/%m/%d %H:%M")
881       
882        file = open(filename,"w")
883        s = "%s %s" % (tmstamp, string_to_file)
884        file.write(s)
885        file.close()       
886
887       
888    # Executes command which starts watchdog (start palm_wd)
889    ########################################################
890    def start_watchdog(self):
891        subprocess.Popen(["nohup","palm_wd",">>","/dev/null", "2>&1","&"])
892
893    # Opens "help" dialog
894    #################################
895    def help(self):       
896        dialog = HelpDialog()
897        dialog.exec_()
898
899    # Opens "about" dialog
900    ##################################
901    def about_gui(self):
902        dialog = AboutDialog()
903        dialog.exec_()
904
905    # commandline to buttons etc
906    ##############################
907    def setup_gui(self, palmrun_str): 
908     
909        #self.palm_logo.setPixmap(QtGui.QPixmap(palm_dir + "/trunk/SCRIPTS/palmrungui_files/logo.png"))   
910     
911        #  Some initial settings
912        user = "" 
913        coupled_run = False 
914        ocean_run   = False 
915        nojob       = False 
916
917        #Split parameters in palmrunline
918        splitline = palmrun_str.split(" -")
919       
920        if ( splitline[0] != "palmrun"):
921            return 1
922
923        else:
924            self.group_execution.setEnabled(True) 
925
926        # Loop for all parameters in palmrunline
927        i = len(splitline)-1
928        while i >= 1:
929
930            # Determine parameter
931            splitparameter = splitline[i].split(" ")
932
933            parameter = splitparameter[0] 
934            splitparameter.pop(0)
935            options = " ".join(splitparameter) 
936            options = options.replace("\"","") 
937
938            # Check for suitable switch
939            if ( parameter == "r"):
940             
941                if ( options != ""):
942                    self.group_execution.findChild(QtGui.QLineEdit,"line_jobname").setText(options) 
943                    nojob = False 
944               
945                else:                 
946                    nojob = True 
947               
948            elif ( parameter == "c"):
949                tmpindex = self.group_execution.findChild(QtGui.QComboBox, "combo_configuration").findText(options.strip(),QtCore.Qt.MatchExactly)
950                if tmpindex != -1: 
951                   self.group_execution.findChild(QtGui.QComboBox, "combo_configuration").setCurrentIndex(tmpindex)
952                else:
953                   self.group_execution.findChild(QtGui.QComboBox, "combo_configuration").setCurrentIndex(0)
954            elif ( parameter == "q"):
955                self.group_execution.findChild(QtGui.QLineEdit,"line_q").setText(options) 
956             
957            elif ( parameter == "A"):
958                self.group_execution.findChild(QtGui.QLineEdit,"line_account").setText(options) 
959             
960            elif ( parameter == "X"):
961                self.group_execution.findChild(QtGui.QLineEdit,"line_pe").setText(options) 
962             
963            elif ( parameter == "T"):
964                self.group_execution.findChild(QtGui.QLineEdit,"line_tpn").setText(options) 
965             
966            elif ( parameter == "t"):
967                self.group_execution.findChild(QtGui.QLineEdit,"line_time").setText(options) 
968             
969            elif ( parameter == "B"):
970                self.group_execution.findChild(QtGui.QCheckBox,"check_delete_tmp_files").setChecked(True) 
971             
972            elif ( parameter == "v"):
973                self.group_execution.findChild(QtGui.QCheckBox,"check_verbose").setChecked(True) 
974                         
975            elif ( parameter == "b"): 
976                self.group_advanced.findChild(QtGui.QCheckBox,"check_b").setChecked(True) 
977             
978            elif ( parameter == "F"):
979                self.group_advanced.findChild(QtGui.QCheckBox,"check_F").setChecked(True) 
980             
981            elif ( parameter == "I"):
982                self.group_advanced.findChild(QtGui.QCheckBox,"check_I").setChecked(True) 
983             
984            elif ( parameter == "k"):
985                self.group_advanced.findChild(QtGui.QCheckBox,"check_k").setChecked(True) 
986             
987            elif ( parameter == "O"): 
988                self.group_advanced.findChild(QtGui.QCheckBox,"check_O").setChecked(True) 
989             
990            elif ( parameter == "x"):             
991                self.group_advanced.findChild(QtGui.QCheckBox,"check_x").setChecked(True) 
992             
993            elif ( parameter == "Z"):
994                self.group_advanced.findChild(QtGui.QCheckBox,"check_Z").setChecked(True) 
995               
996            elif ( parameter == "m"):
997                self.group_advanced.findChild(QtGui.QLineEdit,"line_m").setText(options) 
998             
999            elif ( parameter == "M"):
1000                self.group_advanced.findChild(QtGui.QLineEdit,"line_M").setText(options) 
1001                         
1002            elif ( parameter == "D"):
1003                self.group_advanced.findChild(QtGui.QLineEdit,"line_D").setText(options) 
1004             
1005            elif ( parameter == "c"):
1006                self.group_advanced.findChild(QtGui.QLineEdit,"line_c").setText(options) 
1007                         
1008            elif ( parameter == "s"):
1009                self.group_advanced.findChild(QtGui.QLineEdit,"line_s").setText(options) 
1010             
1011            elif ( parameter == "w"):
1012                self.group_advanced.findChild(QtGui.QLineEdit,"line_w").setText(options) 
1013             
1014
1015            # Determine settings for coupled restart runs
1016            elif ( parameter == "Y"):
1017                optionssplit = options.split(" ") 
1018               
1019                group_coupled = self.group_execution.findChild(QtGui.QGroupBox,"group_coupled")
1020                group_coupled.findChild(QtGui.QLineEdit,"line_PE_atmos").setEnabled(True) 
1021                group_coupled.findChild(QtGui.QLineEdit,"line_PE_ocean").setEnabled(True) 
1022                group_coupled.findChild(QtGui.QLabel,"label_coupled1").setEnabled(True) 
1023                group_coupled.findChild(QtGui.QLabel,"label_coupled2").setEnabled(True) 
1024                group_coupled.findChild(QtGui.QLabel,"label_coupled3").setEnabled(True) 
1025                group_coupled.findChild(QtGui.QLabel,"label_coupling").setEnabled(True) 
1026
1027                if (optionssplit.count() == 2):
1028                    group_coupled.findChild(QtGui.QLineEdit,"line_PE_atmos").setEnabled(optionssplit[0]) 
1029                    group_coupled.findChild(QtGui.QLineEdit,"line_PE_ocean").setEnabled(optionssplit[1])
1030                 
1031                else:                 
1032                    group_coupled.findChild(QtGui.QLineEdit,"line_PE_atmos").setText("") 
1033                    group_coupled.findChild(QtGui.QLineEdit,"line_PE_ocean").setText("") 
1034 
1035                 
1036                coupled_run = True 
1037           
1038            elif ( parameter == "y"):             
1039                self.group_execution.findChild(QtGui.QComboBox, "drop_job").setCurrentIndex(3) 
1040             
1041
1042            # Determine settings for the run control list
1043            elif ( parameter == "a"):
1044             
1045                optionssplit = options.split(" ") 
1046
1047                options_2 = None
1048                options_all = None
1049               
1050                j = 0
1051                while j < len(optionssplit):
1052                 
1053                    options_all = optionssplit[j] 
1054                    options_2 = optionssplit[j][:2] 
1055                                             
1056                    if (options_2 == "d3"):     
1057                        if (options_all[:3][-1] == "#"):
1058                            self.group_execution.findChild(QtGui.QComboBox, "drop_job").setCurrentIndex(0) 
1059                        elif (options_all[:3][-1] == "r"):
1060                            self.group_execution.findChild(QtGui.QComboBox, "drop_job").setCurrentIndex(1) 
1061                       
1062                        elif (options_all[:3][-1] == "o"):
1063                            ocean_run = True 
1064                       
1065                    if (options_all == "restart"):
1066                        self.group_execution.findChild(QtGui.QCheckBox,"check_restarts").setChecked(True) 
1067
1068                    j = j+1
1069
1070            # All unknown parameters are set as extra user parameters
1071            else: 
1072                print parameter
1073                user = "%s-%s \"%s\" " % (user,parameter,options)
1074                splitline.removeAt(i) 
1075
1076            i = i-1
1077        # Change drop box state in case of ocean precursor or coupled restart runs
1078        if ( ocean_run == True ):
1079            if ( coupled_run == True ):
1080                self.group_execution.findChild(QtGui.QComboBox, "drop_job").setCurrentIndex(4) 
1081           
1082            else:
1083                self.group_execution.findChild(QtGui.QComboBox, "drop_job").setCurrentIndex(3) 
1084
1085        if ( user != ""):
1086            self.group_advanced.findChild(QtGui.QLineEdit,"line_user").setText(user)
1087
1088        # Join palmrunline and post it to mainwindow
1089        palmrunline = " -".join(splitline) 
1090        self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText(palmrunline)         
1091
1092        # Disable mainwindow if no job was found, otherwise enable
1093        if ( nojob == True ):
1094            self.group_execution.setEnabled(False) 
1095            self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(False) 
1096            self.menuBar.findChild(QtGui.QMenu,"menuStart").actions()[3].setEnabled(False) 
1097            self.group_execution.findChild(QtGui.QComboBox, "drop_job").setEnabled(False) 
1098            self.group_advanced.setEnabled(False) 
1099            self.check_advanced.setEnabled(False) 
1100            self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(False)
1101         
1102        else:
1103            self.group_execution.setEnabled(True) 
1104            self.groupBox.findChild(QtGui.QPushButton,"button_start").setEnabled(True) 
1105            self.menuBar.findChild(QtGui.QMenu,"menuStart").actions()[3].setEnabled(True)
1106            self.group_execution.findChild(QtGui.QComboBox, "drop_job").setEnabled(True) 
1107            self.group_advanced.setEnabled(True) 
1108            self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setEnabled(True)
1109
1110
1111        self.tabWidget.setCurrentIndex(0)
1112
1113
1114    ## Open from history
1115    ###################################
1116    def open_from_file(self):
1117
1118#      Show History
1119       opt = OpenHistoryBox()
1120       opt.exec_()
1121
1122       if ( history_entry != "" ):
1123          palmrunline = str(history_entry)
1124          palmrunline = palmrunline[17:]
1125          palmrunline = palmrunline[:len(palmrunline)-1]
1126          palmrunline = filter(None,palmrunline.split("("))[0]
1127          self.groupBox.findChild(QtGui.QLineEdit,"commandline").setText(palmrunline)
1128
1129#         Set selected item to jobname in "available jobs" list
1130          jobname = str(history_entry[17:])
1131          jobname = filter(None,jobname.split(" -r"))[1]
1132          jobname = jobname.strip()
1133          jobname = filter(None,jobname.split(" "))[0]
1134          jobname = jobname.replace("\"","")
1135          item2int = self.list_jobs.findItems(jobname,QtCore.Qt.MatchCaseSensitive)
1136
1137          if ( item2int != [] ):
1138             self.list_jobs.setCurrentItem(item2int[0])
1139             self.update_input()
1140
1141#         Add tooltip tag
1142          tag = str(history_entry).split('\n')[0]
1143          tag = filter(None,tag.split("("))[1]
1144          tag = tag.replace(")","")
1145          self.groupBox.findChild(QtGui.QLineEdit,"line_tag").setText(tag)
1146 
1147#         Process palmrungui to set up gui controls
1148          self.setup_gui(palmrunline)
1149
1150
1151    def update_all(self):
1152 
1153       self.setEnabled(False)
1154       self.list_input.clear() 
1155       self.list_user.clear()
1156       self.list_monitoring.clear()
1157       self.list_output.clear()
1158       self.load_jobs()
1159       self.setEnabled(True)
1160       self.update_input()
1161
1162
1163    # Load jobs into list
1164    def load_jobs(self):
1165       
1166       selected_job = self.list_jobs.currentItem()
1167       
1168       if ( selected_job is not None ):
1169          jobname = selected_job.text()
1170       else:
1171          jobname = ""
1172
1173       self.list_jobs.clear() 
1174       self.line_path.setText(job_dir + "/")
1175       
1176       list_of_files = os.listdir(job_dir)
1177     
1178
1179       for i in range(0,len(list_of_files)):
1180          tmp_file = job_dir + "/" + list_of_files[i]
1181
1182          if ( os.path.isdir(tmp_file) ):
1183             self.list_jobs.addItem(str(list_of_files[i]))
1184       
1185
1186
1187       item2int = self.list_jobs.findItems(jobname,QtCore.Qt.MatchCaseSensitive)
1188       
1189       if ( item2int != [] ):
1190          self.list_jobs.setCurrentItem(item2int[0])
1191
1192
1193    # Update input and user code lists
1194    def update_input(self):
1195
1196       self.labeltimer.stop() 
1197
1198     
1199       self.list_input.clear() 
1200       self.list_user.clear()
1201       self.list_monitoring.clear()
1202       self.list_output.clear()
1203       
1204       jobitem = self.list_jobs.currentItem()
1205       
1206       if ( jobitem != None ):
1207       
1208          job_to_show = job_dir + "/" + jobitem.text() + "/INPUT"
1209
1210          if ( os.path.isdir(job_to_show) ):
1211
1212             list_of_files = os.listdir(job_to_show)
1213         
1214             for i in range(0,len(list_of_files)):
1215                tmp_file = job_to_show + "/" + list_of_files[i]
1216             
1217                if ( os.path.isfile(tmp_file) ):
1218                   self.list_input.addItem(str(list_of_files[i]) + " (" + file_size(tmp_file) + ")")
1219 
1220          job_to_show = job_dir + "/" + jobitem.text() + "/USER_CODE"
1221       
1222          if ( os.path.isdir(job_to_show) ):
1223         
1224             list_of_files = os.listdir(job_to_show)
1225         
1226             for i in range(0,len(list_of_files)):
1227                tmp_file = job_to_show + "/" + list_of_files[i]
1228
1229                if ( os.path.isfile(tmp_file) ):
1230                   self.list_user.addItem(str(list_of_files[i]))
1231
1232          job_to_show = job_dir + "/" + jobitem.text() + "/MONITORING"
1233       
1234          if ( os.path.isdir(job_to_show) ):
1235         
1236             list_of_files = os.listdir(job_to_show)
1237         
1238             for i in range(0,len(list_of_files)):
1239                tmp_file = job_to_show + "/" + list_of_files[i]
1240
1241                if ( os.path.isfile(tmp_file) ):
1242                   self.list_monitoring.addItem(str(list_of_files[i]) + " (" + file_size(tmp_file) + ")")
1243
1244          job_to_show = job_dir + "/" + jobitem.text() + "/OUTPUT"
1245
1246          if ( os.path.isdir(job_to_show) ):
1247
1248             list_of_files = os.listdir(job_to_show)
1249
1250             for i in range(0,len(list_of_files)):
1251                tmp_file = job_to_show + "/" + list_of_files[i]
1252
1253                if ( os.path.isfile(tmp_file) ):
1254                   self.list_output.addItem(str(list_of_files[i]) + " (" + file_size(tmp_file) + ")")
1255 
1256          self.group_execution.findChild(QtGui.QLineEdit,"line_jobname").setText(jobitem.text())
1257       self.group_history.findChild(QtGui.QListWidget,"list_jobname").clearSelection()
1258
1259       self.timetimer.start()
1260       self.timer.start(update_frequency)
1261       self.labeltimer.start(update_frequency/10)
1262       self.push_update.setText("Update (" + str(int(update_frequency/1000/60)) + " min)")
1263       QtGui.QApplication.processEvents()
1264
1265       # Change palmrunline accordingly
1266       self.change_commandline("r","")
1267       self.change_commandline("a","") 
1268
1269    # Create a new (empty) job
1270    def create_new_job(self):
1271
1272       self.setEnabled(False)
1273
1274       text, ret = QtGui.QInputDialog.getText(self, "Create new job", "Enter new job name:", mode = QtGui.QLineEdit.Normal, text = '')
1275
1276       if ( ret ):
1277          new_job_name = str(text)
1278       else:
1279          self.setEnabled(True)
1280          return
1281
1282       new_input_dir  = job_dir + "/" + new_job_name + "/INPUT"
1283
1284#      check if a job exists with the new job name. If not, the new job is created and an empty _p3d file is created.
1285       if ( os.path.isdir(new_input_dir) ):
1286          notify = QtGui.QMessageBox.warning(self,'Create new job directory',"Error. Could not create job directory. A job with the new name already exists.")
1287          self.setEnabled(True)
1288          return
1289       else:
1290          os.makedirs(new_input_dir)
1291          os.mknod(new_input_dir + '/' + new_job_name + '_p3d')
1292
1293#      write default namelists into _p3d file
1294       filename = open(new_input_dir + '/' + new_job_name + '_p3d', "w")
1295       filename.write('&initialization_parameters\n    nx = 39,\n    ny = 39,\n    nz = 40,\n    dx = 50.0,\n    dy = 50.0,\n    dz = 50.0,\n/\n\n')
1296       filename.write('&runtime_parameters\n    end_time = 3600.0,\n/\n')
1297       filename.close()
1298
1299
1300#      create empty USER_CODE folder for convenience
1301       new_user_dir  = job_dir + "/" + new_job_name + "/USER_CODE"
1302       os.makedirs(new_user_dir)
1303
1304
1305       self.load_jobs()
1306       self.list_input.clear()
1307       self.list_user.clear()
1308       self.list_monitoring.clear()
1309       self.list_output.clear()
1310       self.setEnabled(True)
1311
1312
1313    # Make a copy of a job
1314    def copy_job(self):
1315 
1316       self.setEnabled(False)
1317       old_job_name = self.list_jobs.currentItem().text()
1318       
1319       text, ret = QtGui.QInputDialog.getText(self, "Copy job", "Enter new job name:", mode = QtGui.QLineEdit.Normal, text = old_job_name)
1320       
1321       if ( ret ):
1322          new_job_name = str(text)
1323       else:
1324           self.setEnabled(True)
1325           return
1326         
1327       new_input_dir  = job_dir + "/" + new_job_name + "/INPUT"
1328
1329#      check if a job exists with the new job name 
1330       if ( os.path.isdir(new_input_dir) ):
1331           notify = QtGui.QMessageBox.warning(self,'Create new job directory',"Error. Could not create job directory. A job with the new name already exists.")
1332           self.setEnabled(True)
1333           return
1334       else:
1335           os.makedirs(new_input_dir)
1336
1337#      copy and rename input files (if present)       
1338       job_to_copy = job_dir + "/" + old_job_name + "/INPUT"
1339
1340       if ( os.path.isdir(job_to_copy) ):
1341
1342          list_of_files = os.listdir(job_to_copy)
1343
1344          for i in range(0,len(list_of_files)):
1345
1346             tmp_file = job_to_copy + "/" + list_of_files[i]         
1347             new_file = new_input_dir + "/" + list_of_files[i].replace(old_job_name, new_job_name)
1348             shutil.copy(tmp_file, new_file)
1349
1350
1351
1352
1353       new_user_dir  = job_dir + "/" + new_job_name + "/USER_CODE"
1354
1355#      check if user code exists in the new job directory
1356       if ( os.path.isdir(new_user_dir) ):
1357           notify = QtGui.QMessageBox.warning(self,'Create new user code directory',"Error. Could not create user code directory. A user code directiory with the new name already exists.")
1358           self.setEnabled(True)
1359           return
1360       else:
1361           os.makedirs(new_user_dir)
1362
1363
1364#      copy user code files (if present)       
1365       user_to_copy = job_dir + "/" + old_job_name + "/USER_CODE"
1366
1367       if ( os.path.isdir(user_to_copy) ):
1368
1369          list_of_files = os.listdir(user_to_copy)
1370         
1371          for i in range(0,len(list_of_files)):
1372
1373             tmp_file = user_to_copy + "/" + list_of_files[i]         
1374             new_file = new_user_dir + "/" + list_of_files[i]
1375             shutil.copy(tmp_file, new_file)
1376
1377       self.load_jobs()
1378       self.list_input.clear() 
1379       self.list_user.clear()
1380       self.list_monitoring.clear()
1381       self.list_output.clear()
1382       self.setEnabled(True)
1383
1384
1385    # Create a whole set of jobs
1386    def create_set(self):
1387 
1388       global set_list
1389#      disable mainwindow 
1390       self.setEnabled(False)
1391     
1392#      show Options Dialog     
1393       opt = CreateSetBox()
1394       opt.exec_()
1395
1396       old_job_name = self.list_jobs.currentItem().text()
1397
1398       for j in range(0,len(set_list)):
1399
1400          if ( set_list[j] != "" ):
1401             new_job_name   = str(set_list[j])
1402             new_input_dir  = job_dir + "/" + str(set_list[j]) + "/INPUT"
1403          else:
1404             continue
1405
1406#         check if a job exists with the new job name 
1407          if ( os.path.isdir(new_input_dir) ):
1408             notify = QtGui.QMessageBox.warning(self,'Create new job directory',"Error. Could not create job directory. A job with the new name already exists.")
1409             self.setEnabled(True)
1410             return
1411          else:
1412             os.makedirs(new_input_dir)
1413
1414#         copy and rename input files (if present)       
1415          job_to_copy = job_dir + "/" + old_job_name + "/INPUT"
1416
1417          if ( os.path.isdir(job_to_copy) ):
1418
1419             list_of_files = os.listdir(job_to_copy)
1420         
1421             for i in range(0,len(list_of_files)):
1422
1423                tmp_file = job_to_copy + "/" + list_of_files[i]         
1424                new_file = new_input_dir + "/" + list_of_files[i].replace(old_job_name, new_job_name)
1425                shutil.copy(tmp_file, new_file)
1426
1427
1428          new_user_dir  = job_dir + "/" + new_job_name + "/USER_CODE"
1429       
1430#         check if user code exists in the new job directory
1431          if ( os.path.isdir(new_user_dir) ):
1432              notify = QtGui.QMessageBox.warning(self,'Create new user code directory',"Error. Could not create user code directory. A user code directiory with the new name already exists.")
1433              self.setEnabled(True)
1434              return
1435          else:
1436              os.makedirs(new_user_dir)
1437
1438
1439#         copy user code files (if present)       
1440          user_to_copy = job_dir + "/" + old_job_name + "/USER_CODE"
1441
1442          if ( os.path.isdir(user_to_copy) ):
1443
1444             list_of_files = os.listdir(user_to_copy)
1445         
1446             for i in range(0,len(list_of_files)):
1447
1448                tmp_file = user_to_copy + "/" + list_of_files[i]         
1449                new_file = new_user_dir + "/" + list_of_files[i]
1450                shutil.copy(tmp_file, new_file)
1451
1452          self.load_jobs()
1453          self.list_input.clear() 
1454          self.list_user.clear()
1455          self.list_monitoring.clear()
1456          self.list_output.clear()
1457
1458       self.setEnabled(True) 
1459       set_list = []
1460
1461
1462 # Add a custom context menu for the job selection list
1463    def openmenujob(self, position):
1464
1465        menu = QtGui.QMenu()
1466
1467
1468        newAction = QtGui.QAction('Create new job', self)
1469        newAction.triggered.connect(self.create_new_job)
1470        menu.addAction(newAction)
1471        selection = self.list_jobs.selectedItems()
1472
1473        if ( len(selection) != 0 ):
1474
1475
1476           copyAction = QtGui.QAction('Copy job', self)
1477           copyAction.triggered.connect(self.copy_job)
1478           createAction = QtGui.QAction('Create set from job', self)
1479           createAction.triggered.connect(self.create_set)
1480           delAction = QtGui.QAction('Delete job', self)
1481           delAction.triggered.connect(self.DeleteJob)
1482
1483           menu.addAction(copyAction)
1484           menu.addAction(createAction)
1485           menu.addAction(delAction)
1486
1487        action = menu.exec_(self.list_jobs.mapToGlobal(position))
1488
1489 # Add a custom context menu
1490    def openmenuinput(self, position):
1491
1492        menu = QtGui.QMenu()
1493
1494        selection = self.list_input.selectedItems()
1495       
1496        if ( len(selection) != 0 ):
1497
1498
1499           openAction = QtGui.QAction('Open file(s)', self)
1500           openAction.setStatusTip('Open file(s) in your favorite editor')
1501           openAction.triggered.connect(self.OpenFilesInput)
1502
1503
1504           delAction = QtGui.QAction('Delete selected file(s)', self)
1505           delAction.triggered.connect(self.DeleteFilesInput)
1506
1507           menu.addAction(openAction)
1508           menu.addAction(delAction)
1509
1510        delallAction = QtGui.QAction('Delete all files', self)
1511        delallAction.triggered.connect(self.DeleteAllFilesInput)
1512        menu.addAction(delallAction)
1513
1514        action = menu.exec_(self.list_input.mapToGlobal(position))
1515
1516 # Add a custom context menu
1517    def openmenuuser(self, position):
1518
1519        menu = QtGui.QMenu()
1520
1521        selection = self.list_user.selectedItems()
1522       
1523        if ( len(selection) != 0 ):
1524
1525           openAction = QtGui.QAction('Open file(s)', self)
1526           openAction.setStatusTip('Open file(s) in your favorite editor')
1527           openAction.triggered.connect(self.OpenFilesUser)
1528
1529
1530           delAction = QtGui.QAction('Delete file(s)', self)
1531           delAction.triggered.connect(self.DeleteFilesUser)
1532
1533           menu.addAction(openAction)
1534           menu.addAction(delAction)
1535
1536        delallAction = QtGui.QAction('Delete all files', self)
1537        delallAction.triggered.connect(self.DeleteAllFilesUser)
1538        menu.addAction(delallAction)
1539
1540        action = menu.exec_(self.list_user.mapToGlobal(position))
1541
1542 # Add a custom context menu
1543    def openmenuoutput(self, position):
1544
1545        menu = QtGui.QMenu()
1546
1547        selection = self.list_output.selectedItems()
1548
1549        if ( len(selection) != 0 ):
1550
1551           openAction = QtGui.QAction('Open file(s)', self)
1552           openAction.setStatusTip('Open file(s) in your favorite editor')
1553           openAction.triggered.connect(self.OpenFilesOutput)
1554
1555           delAction = QtGui.QAction('Delete file(s)', self)
1556           delAction.triggered.connect(self.DeleteFilesOutput)
1557
1558
1559
1560           menu.addAction(openAction)
1561           menu.addAction(delAction)
1562
1563        delallAction = QtGui.QAction('Delete all files', self)
1564        delallAction.triggered.connect(self.DeleteAllFilesOutput)
1565        menu.addAction(delallAction)
1566
1567        action = menu.exec_(self.list_output.mapToGlobal(position))
1568
1569 # Add a custom context menu
1570    def openmenumonitoring(self, position):
1571
1572        menu = QtGui.QMenu()
1573
1574        selection = self.list_monitoring.selectedItems()
1575       
1576        if ( len(selection) != 0 ):
1577
1578           openAction = QtGui.QAction('Open file(s)', self)
1579           openAction.setStatusTip('Open file(s) in your favorite editor')
1580           openAction.triggered.connect(self.OpenFilesMonitoring)
1581
1582           delAction = QtGui.QAction('Delete file(s)', self)
1583           delAction.triggered.connect(self.DeleteFilesMonitoring)
1584
1585
1586
1587           menu.addAction(openAction)
1588           menu.addAction(delAction)
1589
1590        delallAction = QtGui.QAction('Delete all files', self)
1591        delallAction.triggered.connect(self.DeleteAllFilesMonitoring)
1592        menu.addAction(delallAction)
1593
1594        action = menu.exec_(self.list_monitoring.mapToGlobal(position))
1595
1596    def OpenConfig(self):
1597
1598       config = str(self.group_execution.findChild(QtGui.QComboBox, "combo_configuration").currentText())
1599       if ( config != "" ):
1600          filename = ".palm.config." + config
1601          open_file = "xdg-open " + filename
1602          os.system(str(open_file))
1603
1604    def OpenFilesInput(self):
1605   
1606       sel_job = self.list_jobs.currentItem().text()
1607       sel_files = self.list_input.selectedItems()
1608       
1609       input_dir = job_dir + "/" + sel_job + "/INPUT/"
1610       
1611       open_files = ""
1612       for i in range(0,len(sel_files)):
1613          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text().split("(")[0] + "; "
1614
1615       os.system(str(open_files))
1616
1617    def OpenFilesUser(self):
1618   
1619       sel_job = self.list_jobs.currentItem().text()
1620       sel_files = self.list_user.selectedItems()
1621       
1622       input_dir = job_dir + "/" + sel_job + "/USER_CODE/"
1623       
1624       open_files = ""
1625       for i in range(0,len(sel_files)):
1626          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text() + "; "
1627
1628       os.system(str(open_files)) 
1629       selection = self.list_jobs.selectedItems()
1630 
1631    def OpenFilesMonitoring(self):
1632   
1633       sel_job = self.list_jobs.currentItem().text()
1634       sel_files = self.list_monitoring.selectedItems()
1635       
1636       input_dir = job_dir + "/" + sel_job + "/MONITORING/"
1637       
1638       open_files = ""
1639       for i in range(0,len(sel_files)):
1640          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text().split("(")[0]  + "; "
1641
1642       os.system(str(open_files)) 
1643       selection = self.list_jobs.selectedItems()
1644 
1645    def OpenFilesOutput(self):
1646   
1647       sel_job = self.list_jobs.currentItem().text()
1648       sel_files = self.list_output.selectedItems()
1649       
1650       input_dir = job_dir + "/" + sel_job + "/OUTPUT/"
1651       
1652       open_files = ""
1653       for i in range(0,len(sel_files)):
1654          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text().split("(")[0] + "; "
1655
1656       os.system(str(open_files)) 
1657       selection = self.list_jobs.selectedItems()
1658
1659    def DeleteFilesInput(self):
1660
1661       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete these files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1662
1663       if status == QtGui.QMessageBox.Yes:
1664
1665          sel_job = self.list_jobs.currentItem().text()
1666          sel_files = self.list_input.selectedItems()
1667
1668          input_dir = job_dir + "/" + sel_job + "/INPUT/"
1669
1670          for i in range(0,len(sel_files)):
1671             filename = input_dir +  sel_files[i].text().split("(")[0].trimmed()
1672             os.remove(filename)
1673
1674          self.update_all()
1675
1676
1677    def DeleteFilesUser(self):
1678
1679       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete these files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1680
1681       if status == QtGui.QMessageBox.Yes:
1682
1683          sel_job = self.list_jobs.currentItem().text()
1684          sel_files = self.list_user.selectedItems()
1685
1686          input_dir = job_dir + "/" + sel_job + "/USER_CODE/"
1687
1688          for i in range(0,len(sel_files)):
1689             filename = input_dir +  sel_files[i].text().split("(")[0].trimmed()
1690             os.remove(filename)
1691
1692          self.update_all()
1693
1694
1695    def DeleteFilesMonitoring(self):
1696
1697       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete these files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1698
1699       if status == QtGui.QMessageBox.Yes:
1700
1701          sel_job = self.list_jobs.currentItem().text()
1702          sel_files = self.list_monitoring.selectedItems()
1703
1704          input_dir = job_dir + "/" + sel_job + "/MONITORING/"
1705
1706          for i in range(0,len(sel_files)):
1707             filename = input_dir +  sel_files[i].text().split("(")[0].trimmed()
1708             os.remove(filename)
1709
1710          self.update_all()
1711
1712
1713    def DeleteFilesOutput(self):
1714
1715       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete these files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1716
1717       if status == QtGui.QMessageBox.Yes:
1718
1719          sel_job = self.list_jobs.currentItem().text()
1720          sel_files = self.list_output.selectedItems()
1721
1722          input_dir = job_dir + "/" + sel_job + "/OUTPUT/"
1723
1724          for i in range(0,len(sel_files)):
1725             filename = input_dir +  sel_files[i].text().split("(")[0].trimmed()
1726             os.remove(filename)
1727
1728          self.update_all()
1729
1730
1731    def DeleteAllFilesInput(self):
1732
1733       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete all files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1734
1735       if status == QtGui.QMessageBox.Yes:
1736
1737          check = self.list_jobs.currentItem()
1738          if ( check ):
1739             sel_job = self.list_jobs.currentItem().text()
1740             sel_files = self.list_input.selectedItems()
1741
1742             input_dir = job_dir + "/" + sel_job + "/INPUT/"
1743
1744             if os.path.exists(str(input_dir)):
1745                shutil.rmtree(str(input_dir))
1746                os.makedirs(str(input_dir))
1747
1748                self.update_all()
1749
1750
1751    def DeleteAllFilesUser(self):
1752
1753       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete all files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1754
1755       if status == QtGui.QMessageBox.Yes:
1756
1757          check = self.list_jobs.currentItem()
1758          if ( check ):
1759             sel_job = self.list_jobs.currentItem().text()
1760             sel_files = self.list_input.selectedItems()
1761
1762             input_dir = job_dir + "/" + sel_job + "/USER_CODE/"
1763
1764             if os.path.exists(str(input_dir)):
1765                shutil.rmtree(str(input_dir))
1766                os.makedirs(str(input_dir))
1767
1768                self.update_all()
1769
1770
1771
1772    def DeleteAllFilesOutput(self):
1773
1774       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete all files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1775
1776       if status == QtGui.QMessageBox.Yes:
1777
1778          check = self.list_jobs.currentItem()
1779          if ( check ):
1780             sel_job = self.list_jobs.currentItem().text()
1781             sel_files = self.list_input.selectedItems()
1782
1783             input_dir = job_dir + "/" + sel_job + "/OUTPUT/"
1784
1785             if os.path.exists(str(input_dir)):
1786                shutil.rmtree(str(input_dir))
1787                os.makedirs(str(input_dir))
1788
1789                self.update_all()
1790
1791
1792
1793    def DeleteAllFilesMonitoring(self):
1794
1795       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete all files?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1796
1797       if status == QtGui.QMessageBox.Yes:
1798
1799          check = self.list_jobs.currentItem()
1800          if ( check ):
1801             sel_job = self.list_jobs.currentItem().text()
1802             sel_files = self.list_input.selectedItems()
1803
1804             input_dir = job_dir + "/" + sel_job + "/MONITORING/"
1805
1806             if os.path.exists(str(input_dir)):
1807                shutil.rmtree(str(input_dir))
1808                os.makedirs(str(input_dir))
1809
1810                self.update_all()
1811
1812
1813
1814    def DeleteJob(self):
1815
1816       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete this job?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1817
1818       if status == QtGui.QMessageBox.Yes:
1819
1820          sel_job = self.list_jobs.currentItem().text()
1821
1822          input_dir = job_dir + "/" + sel_job
1823          shutil.rmtree(str(input_dir))
1824
1825          self.update_all()
1826
1827# Message box for showing RUN_CONTROL output
1828class CreateSetBox(QtGui.QDialog):
1829    def __init__(self):
1830
1831        super(CreateSetBox, self).__init__()
1832
1833        uic.loadUi(palm_bin + '/palmrungui_files/create_set.ui', self)
1834
1835        self.show()
1836
1837        return
1838
1839#   Cancel button
1840    def rejected(self):
1841
1842       self.close()
1843
1844       return
1845
1846#   OK button
1847    def accept(self):
1848
1849       global set_list
1850
1851       text = self.list.toPlainText() 
1852       set_list = text.split('\n')
1853       self.close()
1854
1855       return
1856
1857# Message box for showing RUN_CONTROL output
1858class OpenHistoryBox(QtGui.QDialog):
1859    def __init__(self):
1860
1861        super(OpenHistoryBox, self).__init__()
1862
1863        uic.loadUi(palm_bin + '/palmrungui_files/history.ui', self)
1864
1865        if os.path.exists(palm_dir + "/.palmrungui.history"):
1866            pass
1867        else:
1868            return
1869
1870        filename = open(palm_dir + "/.palmrungui.history","r")
1871        history = filename.readlines()
1872        filename.close()
1873
1874
1875        list_jobname = self.findChild(QtGui.QListWidget,"list_history")
1876
1877        # Read history entries and append to recent job list
1878        len_history=len(history)-1
1879        i = 0
1880        while i<=len_history:
1881            list_jobname.addItem(history[i])
1882            i = i + 1
1883
1884        self.show()
1885
1886        return
1887
1888#   Select item / activate Load button
1889    def ItemSelected(self):
1890
1891       self.push_open.setEnabled(True)
1892
1893       return
1894
1895
1896#   Load job from history
1897    def OpenFromHistory(self):
1898
1899       global history_entry
1900       history_entry = self.list_history.selectedItems()[0].text()
1901
1902       self.close()
1903
1904       return
1905
1906#   Close history window
1907    def DiscardHistory(self):
1908
1909       global history_entry
1910       history_entry = ""
1911       self.close()
1912
1913       return
1914
1915#   Clear history
1916    def ClearHistory(self):
1917
1918       status = QtGui.QMessageBox.question(self,'Delete Confirmation', "Are you sure you want to delete your history?", QtGui.QMessageBox.Yes | QtGui.QMessageBox.No)
1919
1920       if status == QtGui.QMessageBox.Yes:
1921
1922          if os.path.exists(palm_dir + "/.palmrungui.history"):
1923             os.remove(palm_dir + "/.palmrungui.history")
1924
1925
1926       return
1927
1928if __name__ == "__main__":
1929    app = QtGui.QApplication(sys.argv)
1930    window = Mainwindow()
1931    window.show()
1932    sys.exit(app.exec_())
Note: See TracBrowser for help on using the repository browser.