Open Recent File, Python method

   1818   11   0
User Avatar
Member
143 posts
Joined: July 2015
Offline
Hello

I was trying to find a method to open the most recent file with a hotkey, I didn't find it of course.
but thought about something like a little window populated with all other recent files, sorted out from top to bottom and then I can choose one to open.

I'll be grateful to let me know if there is such a thing possible with Python in Houdini.
User Avatar
Member
311 posts
Joined: Oct. 2016
Offline
Is this not already implemented?

It is like one click on the file menu and some movement. I use this regularily.

Having a hotkey is still a click and then you move the mouse to choose. So it does not seem to improve things much.

Unless you have hidden your menu that is.

Are you sure you need it?

It should be possible to do if really needed.
Interested in character concepts, modeling, rigging, and animation. Related tool dev with Py and VEX.
User Avatar
Member
4521 posts
Joined: Feb. 2012
Offline
MirHadi
Hello

I was trying to find a method to open the most recent file with a hotkey, I didn't find it of course.
but thought about something like a little window populated with all other recent files, sorted out from top to bottom and then I can choose one to open.

I'll be grateful to let me know if there is such a thing possible with Python in Houdini.

Hi, there is no such thing built-in. But you can implement it yourself:

def getRecentHipFiles():
    userdir = hou.getenv('HOUDINI_USER_PREF_DIR')
    file = os.path.join(userdir, "file.history")
    
    validfiles = []
    with open(file) as f:
        lines = f.readlines()
        for line in lines:
            newline = line.strip()
            if newline == "}":
                break;
                
            if newline != "{" and newline != "HIP":
                if os.path.exists(newline):
                    validfiles.append(newline)
            
        
    validfiles.reverse()
    return validfiles

I talk about this exact issue in my GamesCom Asia 2022 talk. It's the only thing I had to create to completely replace the main menu bar. Other actions can be invoked via hotkeys. But if you want to have a popup window populated with recent files with the ability to load them using a hotkey directly from the window using 1-9 keys, you will have to implement this in Qt.

Senior FX TD @ Industrial Light & Magic
Get to the NEXT level in Houdini & VEX with Pragmatic VEX! [www.pragmatic-vfx.com]

youtube.com/@pragmaticvfx | patreon.com/animatrix | pragmaticvfx.gumroad.com
User Avatar
Member
311 posts
Joined: Oct. 2016
Offline
While testing the python keyboard modules I did a mistake and had to redo this quickly. Feel free to update and improve. I'm out of time for now.

import os

def getRecentHipFiles():
    userdir = hou.getenv('HOUDINI_USER_PREF_DIR')
    file = os.path.join(userdir, "file.history")
    
    validfiles = []
    with open(file) as f:
        lines = f.readlines()
        for line in lines:
            newline = line.strip()
            if newline == "}":
                break;
                
            if newline != "{" and newline != "HIP":
                if os.path.exists(newline):
                    validfiles.append(newline)
            
        
    validfiles.reverse()
    return validfiles

    
def createFilesDict(input_list):
    '''Used to create a dict with files from a list of files with absolute paths.'''
    files_dict = {}
    for item in input_list:
        basename = os.path.basename(item)
        files_dict[basename] = item
    return files_dict
    
    
def recentFilesWindow():
    '''Show recent files'''
    files_list = getRecentHipFiles()
    files_dict = createFilesDict(files_list) 
    enumerate_list = []
    
    title = 'Recent Files'    
    message = ''
    c = 1
    
    input_labels = ()
    for k,v in files_dict.items():
        input_labels += (str(c)+' '+k,)
        enumerate_list.append(str(c))
        c += 1
    
    initial_contents = ()
    for v in files_dict.values():
        initial_contents += (v,)
    
    help = """
    Help for choosing:
    
    Please click on the button matching the number of intended file.
    
    """
    
    buttons = (enumerate_list)
    
    severity = hou.severityType.Message
    
    choice, user_contents = hou.ui.readMultiInput(message=message, input_labels=input_labels, password_input_indices=(), 
                          buttons=buttons, severity=severity, 
                          default_choice=0, close_choice=-1, help=help, 
                          title=title, initial_contents=initial_contents)    

recentFilesWindow()
Interested in character concepts, modeling, rigging, and animation. Related tool dev with Py and VEX.
User Avatar
Member
143 posts
Joined: July 2015
Offline
SWest
While testing the python keyboard modules I did a mistake and had to redo this quickly. Feel free to update and improve. I'm out of time for now.

Thank you very much for your time.
It actually look fantastic so far, let's see what can be done to make it complete.
Thank you again
User Avatar
Member
311 posts
Joined: Oct. 2016
Offline
Great, here’s some thoughts just not to forget them.

Required:

The dict function need to be made robust so if there is a key collision the second key name get some number appended.

Alternatively the key itself could just be the number. What would you prefer?

Not essential:

The user content (editable part) could be used so that if a recent file is not specified you could just adjust the string. For example you want version 06 but you have only from version 07 and up. Well just change and open.

However, RFE:s are probably best to do after using the tool for a while.

Anyone can complete this I don’t mind.

Cheers!
Interested in character concepts, modeling, rigging, and animation. Related tool dev with Py and VEX.
User Avatar
Member
311 posts
Joined: Oct. 2016
Offline
This tool will open a window presenting recently opened HIP files. Click on a corresponding number to choose.

To install:
  1. Create a "New Tool" in any Shelf that you prefer
  2. Name it "Recent HIP".
  3. Copy and paste the below Python into the Script part.
  4. Add a Global Hotkey using the Shelf graphical interface for that tool (for example "Ctrl+Shift+O").

Will this work?
Do you have any BUG-reports or requests?

Anyone may update this tool as needed.

import os

def getRecentHipFiles():
    userdir = hou.getenv('HOUDINI_USER_PREF_DIR')
    file = os.path.join(userdir, "file.history")
    
    validfiles = []
    with open(file) as f:
        lines = f.readlines()
        for line in lines:
            newline = line.strip()
            if newline == "}":
                break;
                
            if newline != "{" and newline != "HIP":
                if os.path.exists(newline):
                    validfiles.append(newline)
            
        
    validfiles.reverse()
    return validfiles

    
def createFilesDict(input_list):
    '''Used to create a dict with files from a list of files with absolute paths.'''
    files_dict = {}
    key_collision = False
    for item in input_list:
        c = 1
        basename = os.path.basename(item)
        basename_copy = basename
        # fix key collisions (no duplicates)
        while basename_copy in files_dict.keys():
            key_collision = True
            basename_copy = basename + ' ' + str(c)
            c += 1
        if key_collision:
            basename = basename_copy        
            
        files_dict[basename] = item
    return files_dict
    
    
def recentFilesWindow():
    '''Show recent files. User may edit file paths of recent files.
    User can click on a number corresponding to a list of recent files.'''

    files_list = getRecentHipFiles()
    files_dict = createFilesDict(files_list) 
    enumerate_list = []
    enumerate_list.append('Cancel')
    
    title = 'Open a Recent File'    
    message = '''
    Please click on the button matching the number of intended file to open it.'''
    c = 1
    
    input_labels = ()
    for k,v in files_dict.items():
        input_labels += (str(c)+' '+k,)
        enumerate_list.append(str(c))
        c += 1
    
    initial_contents = ()
    for v in files_dict.values():
        initial_contents += (v,)
    
    help = """
    
    You may edit a path manually if you wish. 
    
    """
    
    buttons = (enumerate_list)
    
    severity = hou.severityType.Message
    
    choice_int, user_contents = hou.ui.readMultiInput(message=message, input_labels=input_labels, password_input_indices=(), 
                          buttons=buttons, severity=severity, 
                          default_choice=0, close_choice=-1, help=help, 
                          title=title, initial_contents=initial_contents)
                          
    # check if file exist: open or feedback
    file_name = user_contents[choice_int-1]
    if (os.path.isfile(file_name) and choice_int != 0 ):
        print(file_name)
        hou.hipFile.load(file_name, suppress_save_prompt=False, ignore_load_warnings=False)  
    if not (os.path.isfile(file_name)):
        message = file_name+' does not exist.'
        temp = hou.ui.displayMessage('Input error: '+message, \
        title='Notification', buttons=('OK',))


recentFilesWindow()
Edited by SWest - Oct. 15, 2023 09:45:20
Interested in character concepts, modeling, rigging, and animation. Related tool dev with Py and VEX.
User Avatar
Member
64 posts
Joined: April 2022
Offline
My version

import os

def getRecentHipFiles():
    userdir = hou.getenv('HOUDINI_USER_PREF_DIR')
    file = os.path.join(userdir, "file.history")
    
    validfiles = []
    with open(file) as f:
        lines = f.readlines()
        for line in lines:
            newline = line.strip()
            if newline == "}":
                break;
                
            if newline != "{" and newline != "HIP":
                if os.path.exists(newline):
                    validfiles.append(newline)
        
    validfiles.reverse()
    return validfiles

files = getRecentHipFiles()
    
if files:
    ids = hou.ui.selectFromList(files, default_choices=(0,), exclusive=True,
                                title="Open Recent Scene", column_header="Recent Scenes",
                                clear_on_cancel=True, width=hou.ui.scaledSize(700))
    
    if ids:
        hou.hipFile.load(files[ids[0]])
alexeyvanzhula.gumroad.com
User Avatar
Member
311 posts
Joined: Oct. 2016
Offline
Aha, there is also a built in selection list hou.ui.selectFromList().

Good to know!
Interested in character concepts, modeling, rigging, and animation. Related tool dev with Py and VEX.
User Avatar
Member
64 posts
Joined: April 2022
Offline
And a more elegant way of selection from a Qt menu

import os
from hutil.Qt.QtWidgets import QMenu
from hutil.Qt.QtGui import QCursor
from hutil.Qt.QtCore import QPoint

def getRecentHipFiles():
    userdir = hou.getenv('HOUDINI_USER_PREF_DIR')
    file = os.path.join(userdir, "file.history")
    
    validfiles = []
    with open(file) as f:
        lines = f.readlines()
        for line in lines:
            newline = line.strip()
            if newline == "}":
                break;
                
            if newline != "{" and newline != "HIP":
                if os.path.exists(newline):
                    validfiles.append(newline)
        
    validfiles.reverse()
    return validfiles
    
files = getRecentHipFiles()

if files:
    menu = QMenu(hou.qt.mainWindow())
    menu.triggered.connect(lambda action: hou.hipFile.load(action.text()))
    [ menu.addAction(f) for f in files ]
    menu.setActiveAction(menu.actions()[0])
    menu.exec_(QCursor.pos() - QPoint(hou.ui.scaledSize(8), hou.ui.scaledSize(8)))
Edited by anon_user_95266836 - Oct. 15, 2023 11:11:46
alexeyvanzhula.gumroad.com
User Avatar
Member
311 posts
Joined: Oct. 2016
Offline
Alexey_Vanzhula
And a more elegant way of selection from a Qt menu

The QT method I would say is clearly the most minimalistic approach. The text also look like it belongs to the interface rather than having some different style. It is also a fast two press/click approach. Nice!
Edited by SWest - Oct. 15, 2023 16:31:08
Interested in character concepts, modeling, rigging, and animation. Related tool dev with Py and VEX.
User Avatar
Member
143 posts
Joined: July 2015
Offline
Alexey_Vanzhula
And a more elegant way of selection from a Qt menu

Thank you very much for your precious time.
This is reachable and highly organized!
Edited by MirHadi - Nov. 16, 2023 08:22:10
  • Quick Links