FileDialog Microservice
Update
The use of a file-provider was deemed to be a better design since this microservice does not need to go through the servemanager layer. See async/paraview!102
Goal
A simple service that allows to browse the filesystem and create/delete directories
FileDialog microservice design
Keep the Model-View-Controller design of the current pqFileDialog
but adapt it to the micro-services design idea.
Steps:
- Bring
pqFileModel
in since it has the required logic already in-place but remove Qt bits (mainly usage ofQString
). - View, and Controller will by handled by python/trame (since they interact with the user),
FileModel
will be wrapped for python. - The actual
FileMicroService
will be only used internally.
Note: We can have an explicit async
function Update()
that updates the model (FileModel1
)
or all "getters" can become async
functions (FileModel2
)
class FileModel1:
{
public:
void SetCurrentPath(std::string path=".")
void Initialize();
std::string GetCurrentPath();
std::vector<std::string> GetCurrentPathListing();
/**
Push current directory to the server and fetch directory listing.
It will be wrapped as:
async def Update() -> bool
**/
rxcpp::observable<bool> Update() {return StatusSubject.get_observable();}
private:
vtkFileMicroService FileMicroService;
rxcpp::subject<bool> StatusSubject;
std::string CurrentPath;
std::vector<std::string> CurrentPathListing;
};
void Initialize()
{
FileMicroService.SetSession(...);
FileService.GetObservable().subscribe([this]vtkVPFileInformation fileInfo)
{
this->CurrentPath = fileInfo.GetCurrentPath();
this->CurrentPathListing = fileInfo.GetPathListing();
StatusSubject.get_subscriber().on_next(true);
});
}
// FileModel2 all "getters" are async functions (`FileModel2`)
class FileModel2:
{
public:
void SetCurrentPath(std::string path=".")
void Initialize();
// will we wrapped as async def GetCurrentPath() -> AsyncIterator[str]
rxcpp::observable<std::string> GetCurrentPath()
{ return this->CurrentPathSubject.get_observable();}
// will we wrapped as async def GetCurrentPathListing() -> AsyncIterator[list[str]]
rxcpp::observable< std::vector<std::string> > GetCurrentPathListing()
{ return this->CurrentPathListing.get_observable();}
private:
vtkFileMicroService FileMicroService;
rxcpp::subject<std::string> CurrentPathSubject;
rxcpp::subject<std::vector<std::string>> CurrentPathListingSubject;
};
void Initialize()
{
FileMicroService.SetSession(...);
FileService.GetObservable().subscribe([]vtkVPFileInformation fileInfo)
{
std::string currentPath = fileInfo.GetCurrentPath();
std::vector<std::string> pathListing = fileInfo.GetPathListing();
CurrentPathSubject.get_subscriber().on_next(currentPath);
CurrentPathListing.get_subscriber().on_next(pathListing);
});
}
class vtkFileMicroService :
{
public:
void SetSession(Session* session);
Session* GetSession();
void SetCurrentPath(std::string path);
rxcpp::observable<vtkPVFileInformation> GetObservable()
{ return this->FileInformationSubject.get_observable(); }
private:
rxcpp::subject<vtkPVFileInformation> FileInformationSubject;
}
void SetCurrentPath(std::string path)
{
vtkPVFileInformation fileInfoRequest;
// populate fileInfo attributes and flags based on path
populate(fielInfoRequest)
auto packet = vtkRemoteObjectProvider::GatherInformation(fileInfoRequest);
auto eventual = this->Session->SendRequest(DATA_SERVER,packet);
eventual.GetObservable()
.observe_on(/* appropriate coordination */) // to avoid blocking
subscribe([this](vtkPacket packet){
vtkPVFileInformation fileInfoResponse;
vtkRemoteObjectProvider::ParseResponse(packet, fileInfoResponse)
this->FileInformationSubject.get_subscriber().on_next(fileInfoResponse);
});
}
Edited by Christos Tsolakis