source: palm/trunk/SCRIPTS/palm_jm @ 4260

Last change on this file since 4260 was 2825, checked in by maronga, 7 years ago

adjustments in gui tools

  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 12.2 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-2018  Leibniz Universitaet Hannover
18##--------------------------------------------------------------------------------#
19#
20# Current revisions:
21# -----------------
22#
23#
24# Former revisions:
25# -----------------
26# $Id: palm_jm 2825 2018-02-20 21:48:27Z hellstea $
27# Modified header
28#
29# 2718 2018-01-02 08:49:38Z maronga
30# Corrected "Former revisions" section
31#
32# 2696 2017-12-14 17:12:51Z kanani
33# Change in file header (GPL part)
34#
35# 2504 2017-09-27 10:36:13Z maronga
36# Bugfix: jobs were not loaded on start.
37#
38# 2484 2017-09-20 14:22:42Z maronga
39# Adapted for palmrun with USER_CODE always stored under /JOBS/name/USER_CODE/.
40# Added PALM logo
41#
42# 2068 2016-11-11 21:59:39Z maronga
43#
44# 2067 2016-11-11 21:55:49Z maronga
45# Minor bugfix: palm_jm can now be called from any location
46#
47# 2065 2016-11-11 12:25:10Z maronga
48# Initial revision
49#
50#
51# Description:
52# ------------
53# PALM job manager works a file manager for PALM input files. It lists all jobs in
54# the working directory and displays associated input and user code files, which
55# can be opened directly from the interface. Also, it is possible to copy jobs and
56# to create entire new sets of jobs based on a reference job.
57#
58# Instructions:
59# -------------
60# 1) Start palm_jm either from mrungui or from shell by "nohup palm_jm&"
61#
62# To do:
63# ------
64# 1) Add display for the MONITORING and OUTPUT folder
65# 2) Add zip function to export single or multiple jobs
66# 3) Allow for copying INPUT files to a remote host
67#------------------------------------------------------------------------------!
68
69import os
70from PyQt4 import QtGui, QtCore, uic
71from PyQt4.QtCore import pyqtSlot,SIGNAL,SLOT
72import shutil
73import subprocess as sub
74import sys
75
76set_list = []
77
78
79# Determine PALM directories
80try: 
81   devnull = open(os.devnull, 'w')
82   out = sub.check_output("echo $PALM_BIN", shell=True, stderr=sub.STDOUT)
83   palm_bin = out.rstrip()
84   palm_dir = out.split("palm")[0] + "palm/" + out.split("palm")[1].split("/")[1]
85   out = None
86     
87   job_dir = palm_dir + '/JOBS'
88   user_dir = palm_dir + '/USER_CODE'
89   
90except:   
91   print "Error. $PALM_BIN is not set."
92   raise SystemExit
93
94
95
96# MainWindow class
97class JobManager(QtGui.QMainWindow):
98   
99    def __init__(self):
100        super(JobManager, self).__init__()
101       
102        self.InitUi()   
103       
104   
105    # Initialized MainWindow UI
106    def InitUi(self):
107
108        # Load predefined mainwindow
109        uic.loadUi(palm_bin + '/palm_jm_files/palm_jm.ui', self)
110
111        self.palm_logo.setPixmap(QtGui.QPixmap(palm_dir  + "/trunk/SCRIPTS/palmrungui_files/logo.png"))
112
113
114   
115        # Display MainWindow
116        self.show()
117        QtGui.QApplication.processEvents()
118
119        self.load_jobs()
120
121   
122    def update_all(self):
123 
124       self.setEnabled(False)
125       self.list_input.clear() 
126       self.list_user.clear()
127       self.load_jobs()
128       self.setEnabled(True)
129
130    # Load jobs into list
131    def load_jobs(self):
132       
133       self.list_jobs.clear() 
134       self.push_copy.setEnabled(False)
135       self.push_create_set.setEnabled(False)     
136     
137       self.line_path.setText(job_dir + "/")
138       
139       list_of_files = os.listdir(job_dir)
140             
141       for i in range(0,len(list_of_files)):
142          tmp_file = job_dir + "/" + list_of_files[i]
143
144          if ( os.path.isdir(tmp_file) ):
145             self.list_jobs.addItem(str(list_of_files[i]))
146
147
148    # Update input and user code lists
149    def update_input(self):
150     
151       self.list_input.clear() 
152       self.list_user.clear()
153       self.push_copy.setEnabled(True)
154       self.push_create_set.setEnabled(True)
155     
156       job_to_show = job_dir + "/" + self.list_jobs.currentItem().text() + "/INPUT"
157
158       if ( os.path.isdir(job_to_show) ):
159
160          list_of_files = os.listdir(job_to_show)
161         
162          for i in range(0,len(list_of_files)):
163             tmp_file = job_to_show + "/" + list_of_files[i]
164             
165             if ( os.path.isfile(tmp_file) ):
166                self.list_input.addItem(str(list_of_files[i]))
167 
168       job_to_show = job_dir + "/" + self.list_jobs.currentItem().text() + "/USER_CODE"
169       
170       if ( os.path.isdir(job_to_show) ):
171         
172          list_of_files = os.listdir(job_to_show)
173         
174          for i in range(0,len(list_of_files)):
175             tmp_file = job_to_show + "/" + list_of_files[i]
176
177             if ( os.path.isfile(tmp_file) ):
178                self.list_user.addItem(str(list_of_files[i]))
179 
180 
181    # Make a copy of a job
182    def copy_job(self):
183 
184       self.setEnabled(False)
185       old_job_name = self.list_jobs.currentItem().text()
186       
187       text, ret = QtGui.QInputDialog.getText(self, "Copy job", "Enter new job name:", mode = QtGui.QLineEdit.Normal, text = old_job_name)
188       
189       if ( ret ):
190          new_job_name = str(text)
191       else:
192           self.setEnabled(True)
193           return
194         
195       new_input_dir  = job_dir + "/" + new_job_name + "/INPUT"
196
197#      check if a job exists with the new job name 
198       if ( os.path.isdir(new_input_dir) ):
199           notify = QtGui.QMessageBox.warning(self,'Create new job directory',"Error. Could not create job directory. A job with the new name already exists.")
200           self.setEnabled(True)
201           return
202       else:
203           os.makedirs(new_input_dir)
204
205#      copy and rename input files (if present)       
206       job_to_copy = job_dir + "/" + old_job_name + "/INPUT"
207
208       if ( os.path.isdir(job_to_copy) ):
209
210          list_of_files = os.listdir(job_to_copy)
211         
212          for i in range(0,len(list_of_files)):
213
214             tmp_file = job_to_copy + "/" + list_of_files[i]         
215             new_file = new_input_dir + "/" + list_of_files[i].replace(old_job_name, new_job_name)
216             shutil.copy(tmp_file, new_file)
217
218
219
220
221       new_user_dir  = job_dir + "/" + new_job_name + "/USER_CODE"
222       
223#      check if user code exists in the new job directory
224       if ( os.path.isdir(new_user_dir) ):
225           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.")
226           self.setEnabled(True)
227           return
228       else:
229           os.makedirs(new_user_dir)
230
231
232#      copy user code files (if present)       
233       user_to_copy = job_dir + "/" + old_job_name + "/USER_CODE"
234
235       if ( os.path.isdir(user_to_copy) ):
236
237          list_of_files = os.listdir(user_to_copy)
238         
239          for i in range(0,len(list_of_files)):
240
241             tmp_file = user_to_copy + "/" + list_of_files[i]         
242             new_file = new_user_dir + "/" + list_of_files[i]
243             shutil.copy(tmp_file, new_file)
244
245       self.load_jobs()
246       self.list_input.clear() 
247       self.list_user.clear()
248       self.setEnabled(True)
249
250
251    # Create a whole set of jobs
252    def create_set(self):
253 
254       global set_list
255#      disable mainwindow 
256       self.setEnabled(False)
257     
258#      show Options Dialog     
259       opt = CreateSetBox()
260       opt.exec_()
261
262       old_job_name = self.list_jobs.currentItem().text()
263
264       for j in range(0,len(set_list)):
265
266          if ( set_list[j] != "" ):
267             new_job_name   = str(set_list[j])
268             new_input_dir  = job_dir + "/" + str(set_list[j]) + "/INPUT"
269          else:
270             continue
271
272#         check if a job exists with the new job name 
273          if ( os.path.isdir(new_input_dir) ):
274             notify = QtGui.QMessageBox.warning(self,'Create new job directory',"Error. Could not create job directory. A job with the new name already exists.")
275             self.setEnabled(True)
276             return
277          else:
278             os.makedirs(new_input_dir)
279
280#         copy and rename input files (if present)       
281          job_to_copy = job_dir + "/" + old_job_name + "/INPUT"
282
283          if ( os.path.isdir(job_to_copy) ):
284
285             list_of_files = os.listdir(job_to_copy)
286         
287             for i in range(0,len(list_of_files)):
288
289                tmp_file = job_to_copy + "/" + list_of_files[i]         
290                new_file = new_input_dir + "/" + list_of_files[i].replace(old_job_name, new_job_name)
291                shutil.copy(tmp_file, new_file)
292
293
294          new_user_dir  = job_dir + "/" + new_job_name + "/USER_CODE"
295       
296#         check if user code exists in the new job directory
297          if ( os.path.isdir(new_user_dir) ):
298              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.")
299              self.setEnabled(True)
300              return
301          else:
302              os.makedirs(new_user_dir)
303
304
305#         copy user code files (if present)       
306          user_to_copy = job_dir + "/" + old_job_name + "/USER_CODE"
307
308          if ( os.path.isdir(user_to_copy) ):
309
310             list_of_files = os.listdir(user_to_copy)
311         
312             for i in range(0,len(list_of_files)):
313
314                tmp_file = user_to_copy + "/" + list_of_files[i]         
315                new_file = new_user_dir + "/" + list_of_files[i]
316                shutil.copy(tmp_file, new_file)
317
318          self.load_jobs()
319          self.list_input.clear() 
320          self.list_user.clear()
321
322       self.setEnabled(True) 
323   
324   
325 # Add a custom context menu
326    def openmenuinput(self, position):
327
328        menu = QtGui.QMenu()
329
330        selection = self.list_input.selectedItems()
331       
332        if ( len(selection) != 0 ):
333
334           openAction = menu.addAction('Open selected files')     
335           openAction.setStatusTip('Open file(s) in your favorite editor')
336           openAction.triggered.connect(self.OpenFilesInput)
337           action = menu.exec_(self.list_input.mapToGlobal(position))
338
339 # Add a custom context menu
340    def openmenuuser(self, position):
341
342        menu = QtGui.QMenu()
343
344        selection = self.list_user.selectedItems()
345       
346        if ( len(selection) != 0 ):
347
348           openAction = menu.addAction('Open selected files')     
349           openAction.setStatusTip('Open file(s) in your favorite editor')
350           openAction.triggered.connect(self.OpenFilesUser)
351           action = menu.exec_(self.list_user.mapToGlobal(position))
352
353
354    def OpenFilesInput(self):
355   
356       sel_job = self.list_jobs.currentItem().text()
357       sel_files = self.list_input.selectedItems()
358       
359       input_dir = job_dir + "/" + sel_job + "/INPUT/"
360       
361       open_files = ""
362       for i in range(0,len(sel_files)):
363          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text() + "; "
364
365       os.system(str(open_files))
366
367    def OpenFilesUser(self):
368   
369       sel_job = self.list_jobs.currentItem().text()
370       sel_files = self.list_user.selectedItems()
371       
372       input_dir = job_dir + "/" + sel_job + "/USER_CODE/"
373       
374       open_files = ""
375       for i in range(0,len(sel_files)):
376          open_files = open_files + "xdg-open " + input_dir +  sel_files[i].text() + "; "
377
378       os.system(str(open_files)) 
379       selection = self.list_jobs.selectedItems()
380 
381 
382 
383# Message box for showing RUN_CONTROL output
384class CreateSetBox(QtGui.QDialog):
385    def __init__(self):
386     
387        super(CreateSetBox, self).__init__()
388       
389        uic.loadUi(palm_bin + '/palm_jm_files/palm_jm_create_set.ui', self)
390       
391        self.show()
392       
393        return
394
395#   Cancel button
396    def rejected(self):
397     
398       self.close()
399     
400       return
401 
402
403#   OK button
404    def accept(self):
405     
406       global set_list
407       
408       text = self.list.toPlainText() 
409       set_list = text.split('\n')
410       self.close()
411     
412       return
413 
414# Main loop       
415def main():
416   
417    app = QtGui.QApplication(sys.argv)
418    res = JobManager() 
419    sys.exit(app.exec_())
420
421
422if __name__ == '__main__':
423    main()   
Note: See TracBrowser for help on using the repository browser.