Added select flow dialog
diff --git a/common/project_manager.py b/common/project_manager.py
index 1a95841..76d353b 100755
--- a/common/project_manager.py
+++ b/common/project_manager.py
@@ -716,7 +716,60 @@
     def apply(self):
         return self.nentry.get(), self.project_pdkdir, self.projectpath, self.importoption.get()
     
+#------------------------------------------------------
+# Dialog to import a project into the project manager
+#------------------------------------------------------
     
+class SelectFlowDialog(tksimpledialog.Dialog):
+    def body(self, master, warning, seed='', is_subproject = False):
+        self.wait_visibility()
+        if warning:
+            ttk.Label(master, text=warning).grid(row = 0, columnspan = 2, sticky = 'wns')
+        
+        ttk.Label(master, text="Flow:").grid(row = 1, column = 0)
+        
+        project_flows = {
+            'Analog':'Schematic, Simulation, Layout, DRC, LVS',
+            'Digital':'Preparation, Synthesis, Placement, Static Timing Analysis, Routing, Post-Route STA, Migration, DRC, LVS, GDS, Cleanup',
+            'Mixed-Signal':'',
+            'Assembly':'',
+        }
+        
+        subproject_flows = {
+            'Analog':'Schematic, Simulation, Layout, DRC, LVS',
+            'Digital':'Preparation, Synthesis, Placement, Static Timing Analysis, Routing, Post-Route STA, Migration, DRC, LVS, GDS, Cleanup',
+            'Mixed-Signal': '',
+        }
+        self.flows = subproject_flows if is_subproject else project_flows
+        self.flowvar = tkinter.StringVar(master, value = 'Analog')
+        
+        self.infolabel = ttk.Label(master, text=self.flows[self.flowvar.get()], style = 'brown.TLabel', wraplength=250)
+        self.infolabel.grid(row = 2, column = 0, columnspan = 2, sticky = 'news')
+        
+        self.option_menu = ttk.OptionMenu(
+            master,
+            self.flowvar,
+            self.flowvar.get(),
+            *self.flows.keys(),
+            command=self.show_info
+        )
+        
+        self.option_menu.grid(row = 1, column = 1)
+
+        return self.option_menu# initial focus
+    
+    def show_info(self, args):
+        key = self.flowvar.get()
+        print(key)
+        desc = self.flows[key]
+        if desc == '':
+            self.infolabel.config(text='(no description available)')
+        else:
+            self.infolabel.config(text=desc)
+    
+
+    def apply(self):
+        return str(self.flowvar.get())  # Note converts StringVar to string
         
 #------------------------------------------------------
 # Project Manager class
@@ -888,7 +941,7 @@
         self.projectselect.populate("Available Projects:", projectlist,
 			[["New", True, self.createproject],
 			 ["Import", True, self.importproject],
-			 ["Flow", False, self.synthesize],
+			 ["Flow", False, self.startflow],
 			 ["Copy", False, self.copyproject],
 			 ["Rename", False, self.renameproject],
 			 ["Delete", False, self.deleteproject],
@@ -2254,7 +2307,7 @@
     def create_yaml(self, ipname, pdk_dir, description="(Add project description here)"):
         # ipname: Project Name
         data = {}
-        project={}
+        project= {}
         project['description'] = description
         try:
             project['foundry'], foundry_name, project['process'], pdk_desc, pdk_stat = self.pdkdir2fnd( pdk_dir )
@@ -2262,6 +2315,7 @@
             # Cannot parse PDK name, so foundry and node will remain undefined
             pass
         project['project_name'] = ipname
+        project['flow'] = 'none'
         data['project']=project
         return data
     #------------------------------------------------------------------------
@@ -3437,7 +3491,57 @@
                 print('Error copying files: ' + e)
         '''
 
+#----------------------------------------------------------------------
+    # Allow the user to choose the flow of the project
     #----------------------------------------------------------------------
+    
+    def startflow(self, value):
+        projectpath = value['values'][0]
+        flow = ''
+        warning = 'Select a flow for '+value['text']
+        is_subproject = False
+        try:
+            with open(os.path.expanduser(currdesign), 'r') as f:
+                pdirCur = f.read().rstrip()
+                if ('subcells' in pdirCur):
+                    # subproject is selected
+                    is_subproject = True      
+        except:
+            pass
+        if not os.path.exists(projectpath + '/info.yaml'):
+            project_pdkdir = self.get_pdk_dir(projectpath, path=True)
+            data = self.create_yaml(os.path.split(projectpath)[1], project_pdkdir)
+            with open(projectpath + '/info.yaml', 'w') as ofile:
+                print('---',file=ofile)
+                yaml.dump(data, ofile)
+        
+        # Read yaml file for the selected flow
+        with open(projectpath + '/info.yaml','r') as f:
+            data = yaml.safe_load(f)
+            project = data['project']
+            if 'flow' in project.keys() and project['flow']=='none' or 'flow' not in project.keys():
+                while True:
+                    try:
+                        flow = SelectFlowDialog(self, warning, seed='', is_subproject = is_subproject).result
+                    except TypeError:
+                        # TypeError occurs when "Cancel" is pressed, just handle exception.
+                        return None
+                    if not flow:
+                        return None	# Canceled, no action.
+                    break
+                project['flow']=flow
+                data['project']=project
+                with open(projectpath + '/info.yaml', 'w') as ofile:
+                    print('---',file=ofile)
+                    yaml.dump(data, ofile)
+            else:
+                flow = project['flow']
+        
+        print("Starting "+flow+" flow...")
+        if flow.lower() == 'digital':
+            self.synthesize()
+        
+ #----------------------------------------------------------------------
     # Change a project IP to a different name.
     #----------------------------------------------------------------------
 
@@ -3744,9 +3848,9 @@
 
     def synthesize(self):
         value = self.projectselect.selected()
-        print(value)
         if value:
-            design = value['values'][0]
+            design = value['values'][0] # project path
+            pdkdir = self.get_pdk_dir(design, path = True)
             # designname = value['text']
             designname = self.project_name
             development = self.prefs['devstdcells']
@@ -3763,7 +3867,6 @@
             # file.  If there is more than one, then present a list.  If there is
             # only one but it is not in 'qflow/', then be sure to pass the actual
             # directory name to the qflow manager.
-
             qvlist = glob.glob(design + '/*/qflow_vars.sh')
             qvlist.extend(glob.glob(design + '/qflow/*/qflow_vars.sh'))
             if len(qvlist) > 1 or (len(qvlist) == 1 and not os.path.exists(design + '/qflow/qflow_vars.sh')):
@@ -3780,21 +3883,24 @@
                 pname = ppath.replace(design + '/', '')
 
                 print('Synthesize design in qflow project directory ' + pname)
+                print('Loading digital flow manager...')
+                #TODO: replace hard-coded path with function that gets the qflow manager path
                 if development:
-                    subprocess.Popen([config.apps_path + '/qflow_manager.py',
+                    subprocess.Popen(['/usr/local/share/qflow/scripts/qflow_manager.py',
 				design, '-development', '-subproject=' + pname])
                 else:
-                    subprocess.Popen([config.apps_path + '/qflow_manager.py',
+                    subprocess.Popen(['/usr/local/share/qflow/scripts/qflow_manager.py',
 				design, '-subproject=' + pname])
             else:
                 print('Synthesize design ' + designname + ' (' + design + ')')
+                print('Loading digital flow manager...')
                 # use Popen, not run, so that application does not wait for it to exit.
                 if development:
-                    subprocess.Popen([config.apps_path + '/qflow_manager.py',
-				design, designname, '-development'])
+                    subprocess.Popen(['/usr/local/share/qflow/scripts/qflow_manager.py',
+				pdkdir, design, designname, '-development'])
                 else:
-                    subprocess.Popen([config.apps_path + '/qflow_manager.py',
-				design, designname])
+                    subprocess.Popen(['/usr/local/share/qflow/scripts/qflow_manager.py',
+                pdkdir, design, designname])
         else:
             print("You must first select a project.", file=sys.stderr)
 
diff --git a/common/treeviewchoice.py b/common/treeviewchoice.py
index 4bf76ea..35a0570 100755
--- a/common/treeviewchoice.py
+++ b/common/treeviewchoice.py
@@ -60,17 +60,24 @@
             # button widget, and the second is a boolean that is True if the
             # button is to be present always, False if the button is only
             # present when there are entries in the itemlist.
+            if(button[0]=='Flow'):
+                self.flowcallback = func
+                
             self.func_buttons.append([ttk.Button(buttonFrame, text=button[0],
 			style = 'normal.TButton',
 			command = lambda func=func: self.func_callback(func)),
 			button[1]])
-
+			
         self.selectcallback = None
         self.lastselected = None
         self.lasttag = None
         self.treeView.bind('<<TreeviewSelect>>', self.retag)
         self.repopulate(itemlist, versioning)
+        self.treeView.bind('<Double-1>', self.test_callback)
 
+    def test_callback(self, event):
+        self.flowcallback(self.treeView.item(self.treeView.selection()))
+        
     def get_button(self, index):
         if index >= 0 and index < len(self.func_buttons):
             return self.func_buttons[index][0]
@@ -269,6 +276,10 @@
                 valuelist.insert(n,item)
             n += 1
         
+    def double_click(self, event):
+        item = self.treeView.selection()[0]
+        print("you clicked on", self.treeView.item(item,"text"))
+        
     def func_callback(self, callback, event=None):
         callback(self.treeView.item(self.treeView.selection()))