简体   繁体   中英

Pop-up warning if directory contains file before selecting it [Python, traitsui]

I'm using enthought traitsui and traits modules to make a simple GUI.

The code I have for now is shown bellow. I'm looking for a way to pop-up a warning if the "base directory" of a new Study_info instance contains a file called "conf.txt" before selecting it. I then create a new Study instance if the study_info.base directory doesn't contains the "conf.txt" file or if the user agrees to proceed when the warning pops-up.

Currently, I check if the file exists in the folder after clicking on the 'OK' button of the "New study window" window. I wondered if there's a way to make the warning pop-up before (just after clicking on "Ok" in the directory browsing window), so that if the user clicks on "Cancel", he/she can directly click on "browse" again to select another folder (without going back to the "Main window" window). Now, the user has to click on "New Study" in order to select another folder.

from traitsui.api import *
from traits.api import *
import os

class Study_info(HasTraits):
    base_directory = Directory(exists=True)
    new_study_view = View('base_directory',title="New study window", buttons=['OK','Cancel'],kind='modal')
    warning_msg = '\nWarning: Folder already contains configuration file.\n\nProceed ?\n'
    warning = View(Item('warning_msg',show_label=False,style='readonly'),title='Warning',kind='modal',buttons = ['OK','Cancel'])

class Study(HasTraits):
    def __init__(self, study_info):
        self.base_directory = study_info.base_directory
    # plus some other processing stuff
    view = View(Item('base_directory',style='readonly'))

class study_handler(Handler):
    def new_study(self, ui_info):
        new_study_info = Study_info()
        ns_res = new_study_info.configure_traits(view='new_study_view')
        if ns_res and os.path.exists(new_study_info.base_directory):
            new_study = Study(new_study_info)
            if os.path.exists(os.path.join(new_study.base_directory,'conf.txt')):
                warn_res = new_study_info.configure_traits(view='warning')
                if warn_res:
                    ui_info.ui.context["object"].study = new_study
            else:
                ui_info.ui.context["object"].study = new_study

class GUI(HasTraits):
    study = Instance(HasTraits)
    new_study = Action(name="New Study",action="new_study")
    view = View(Item('study',style='custom',show_label=False),buttons = [new_study], handler = study_handler(),title="Main window",resizable=True)

g = GUI()
g.configure_traits()

Any ideas ? Is there a way to overwrite whatever checks that the directory is a directory that exists, so that it also checks if the file inside the folder exists ? How to link this to open the warning window ?

Many thanks in advance !

In this code:

warn_res = new_study_info.configure_traits(view='warning')
if warn_res:
  ui_info.ui.context["object"].study = new_study

it seems like you are assuming something along the lines that configure_traits will return true if the user clicks OK and false otherwise. This is not at all what configure_traits does. (I guess this might actually be partly true, but the return value of configure_traits is not specified in any documentation that I can find).

To be precise, configure_traits creates a view corresponding to its model (context) object and displays this view on the screen and then starts its event loop, which takes over the main thread (so that control is not returned until the dialog exits).

To do what you are trying to do, you should not try to rely on configure_traits or its return value to execute control flow. Instead you should use traits' rich system of event handling. Here is a simple example that is intended more to illustrate event handling and specific handler operations that may be necessary for what you want to do, than to directly solve the task you asked for (there are a few differences, mainly because I didnt want to write more text and add a third, somewhat superfluous dialog as in your example):

class WarningWindow(Handler):
  finished=Bool
  notify=Event

  def init_info(self,info):
    self.finished=False

  #this is a method defined on the handler that executes when the window closes
  #
  #is_ok is True if the user closed the window ok and False if the user closed 
  #the window some other way such as clicking cancel or via the window manager
  def closed(self,info,is_ok):
    self.finished=is_ok
    self.notify=True

  view=View(Label('WARNING: YOU WILL BE EATEN BY A GRUE'),buttons=OKCancelButtons)

class StudyMenu(Handler):
  warning_window=Instance(WarningWindow)
  dir=Directory
  make_study_button=Button('Make new study')
  info=Instance(UIInfo)

  def make_study(self):
    print "now make the study"

  def _make_study_button_fired(self):
    if os.path.exists(os.path.join(self.dir,'conf.txt')):
      warning_window.edit_traits()  #note, not configure_traits

  @on_trait_change('warning_window:notify')
  def warning_window_listen(self):
    if self.warning_window.finished:
    #user is OK to overwrite the conf file
       self.make_study()
    else:
    #user does not want to overwrite
       self.info.ui.dispose() #this discards the window
                              #which is the main window in this example
       print "everything is terrible!"
       sys.exit(666)

  #this is a handler method that executes when the window opens. its primary
  #purpose here is to store the window's UIInfo object in the model object.
  def init_info(self,info):
    self.info=info

StudyMenu().configure_traits()

If you need to check if a particular directory is empty or not you can use os.listdir() method. Here is a quick example. I have an empty folder named as test at c:\\ drive I can use the following code to test if it is empty or not.

import os

dir='c:\\test'
if not os.listdir(dir):
    print "Empty Dir."

You can change the value of dir to test for any other directory!

If you want to check if the directory contains a particular file then you can use the following code. It works same like above code it first checks if the directory is empty or not. If it is not empty then it gets the list of all the files in it. Then it checks if there is a file with the name that you'll specify in the script. For eg: In my case I have a file named as test.txt in the directory c:\\test . Here is the complete code:

import os
dir = "C:\\test"
fileName = "test.txt"
if not os.listdir(dir):
    print "Empty directory."
else:
    filesList = os.listdir(dir)
    for i in range(0,len(filesList)):
        if filesList[i]=="test.txt":
            print "Yes, there is a file with name %s in %s"%(fileName,dir)
        else:
            pass

The output in my case was:

Yes, there is a file with name test.txt in C:\test

Please be advised that this script just checks for the file in a given directory, if the directory contains any sub directories then this script will not check them. This is something that you can try by your own. ;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM