tsc_ImportFilter

This API class provides a way to add items to the File format dropdown list on the Import form and provide a conversion from any input format. The Import form is accessed in TA from the Import softkey on the Job management form. 

The tsc_ImportFilter class must be subclassed and three virtual methods overridden to handle the format conversion.

The API has a Register method which supplies a new item for the format dropdown list and a list of file masks to match the importable file names. File formats are specified as an x_Code, either a Trimble Access code (X_name) or defined in the plugin (PX_name).

One subclass may add multiple file format items to the Import form and they all will call the same conversion methods, and this system can be employed when multiple formats have similar conversions.

Multiple subclasses may be defined to allow different conversion methods to be used. Regardless of when and how items are added or removed, the Import's form file format dropdown list will always appear in alphabetical sequence of the format's translated name.

When any tsc_ImportFilter based method is chosen in the drop-down list, the form is redrawn to shown only the list and the filename selection controls.

Please note that for text input, tsc_File will recognise and read various encodings - UTF-8, plain ASCII, UTF-16, UCS-2, big or little endian, and all cr/lf line endings. If anything else is required, C++ standard library methods may be used to read the file, perform encoding conversions, and so forth. 

Lifetime

Because the user, not the plugin,  is controlling when the Import form is displayed, it is necessary to create a long-lasting instance of the tsc_ImportFilter subclass and register this instance with the form. This registration is tied to the plugin app such that all registered items will be added to the form while the plugin app is active (selected in the App chooser form).

The recommended place to store instances of import filters is in the subclassed tsc_Application, since that will have an appropriate lifetime. This is shown in the example further down.

It is possible to register and deregister import file formats during plugin operation if that is desired.

Enumeration

The way in which the insertion of multiple points with the same name are handled is controlled by this enumeration. It may be set on a per-conversion basis.

enum tsc_ImportDuplicatePointMode : int

{

    ImportMode_Overwrite,     // Replaces the earlier point.

    ImportMode_StoreAnother,  // Stores another instance of the point.

    ImportMode_Ignore         // Stores nothing new.

};

Public methods

void Register (x_Code fileFormat, const char* fileMasks);
Registering a filter requires an instance of this class to be created and the Register method called.
fileFormat determines the text in the drop-down list and also identifies this filter.
fileMasks restricts the files allowed, for example: "*.tsv;*.txt"

Register may be called multiple times for different formats in one instance of tsc_ImportFilter, or multiple instances may be used.

void Deregister (x_Code fileFormat);
To undo the effect of Register, use the Deregister method. When the class instance is destroyed, all registration file types are deregistered.

virtual x_Code OnImportFileSelected (
              x_Code fileFormat,
              const char* filePath,
              tsc_ImportDuplicatePointMode& duplicatePointMode) = 0;

Override to provide an event handler which is called when the Import form is accepted by the user.
fileFormat indicates which menu item was chosen.
filePath contains the full path of the chosen file.
duplicatePointMode can be set to control how duplicate point names are handled by TA. The default is to overwrite previous occurrences.

In this handler, initialize your import filter, such as opening the input file.
Return X_NULL if the the file was opened successfully, or some x_Code that describes the problem. The translation will be presented to the user in an error dialog.

virtual tsc_String OnImportNextRecord (x_Code fileFormat) = 0;
Override this event handler to provide the next record to the importer. The function is called continuously until the end of the file is indicated by this function returning an empty string.
The format of the string returned should be in the "usual" TA CSV format:
"pointname",northing,easting,elevation,"code"
The pointname and code fields should be enclosed in quotes and, as UTF-8, may contain most unicode characters. The code and elevation fields  may be omitted.
The coordinate distance units used are from the currently configured distance settings, and will, if necessary, be converted to internal metric values.

Note: There's a length restriction on the returned string, currently 1024 bytes, and any excess will be silently truncated.

virtual void OnImportClose (x_Code fileFormat) = 0;
Override this method and supply an event handler to be called when the importer has finished. Typically you would close the input file.
It is also important to reset the instance back to a state ready for another import.

Sample code

This sample is a very simple CSV importer that accepts semicolons instead of commas for the field delimiters.

Application.h

class Application : public tsc_Application

{

public:

    Application();

    virtual ~Application();


    tsc_String               GetProductName() const override;

    tsc_String               GetProductDescription() const override;

    tsc_String               GetProductSupportString() const override;

    tsc_String               GetProductEula() const override;

    bool                     ShowSplashScreen() const override;

    bool                     IsAutoConnectRequired() const override;

    bool                     IsOpenJobRequired() const override;

    bool                     HasInstrumentInteraction() const override;

    class tsc_AppMainMenu*   MakeMainMenu() const override;


    class Importer* importer;

};

Application.cpp

#include "Importer.h"


Application::Application()

{

    importer = new Importer;

}


Application::~Application()

{

    delete importer;

}

Importer.cpp

// This example reads a semicolon separated file and converts the lines to CSV.

// The simplified conversion doesn't take account of quotes in strings.

//

class Importer : public tsc_ImportFilter

{

public:

    Importer()

    {

        Register (PX_TestImport, "*.scsv;*.ssv");

    }


    x_Code OnImportFileSelected (

        x_Code , 

        const char* filePath, 

        tsc_ImportDuplicatePointMode& duplicatePointMode) override

    {

        duplicatePointMode = tsc_ImportDuplicatePointMode::ImportMode_StoreAnother;

        tsc_File ifile;

        AllLines = ifile.ReadAllLines (filePath);

        NextLine = 0;


        return (ifile.GetLastError() != 0) ? X_FailedToOpenCSVFile : X_NULL;

    }


    // Feed all of the previously read lines from the file to Trimble Access,

    // except for empty lines which would prematurely end the import.

    //

    tsc_String OnImportNextRecord (x_Code) override

    {

        tsc_String line;


        while (line.IsEmpty())

        {

            if (NextLine >= AllLines.Count())

            {

                return line;

            }

            line = AllLines[NextLine++];

        }

        return line.Replace (";", ",", Replace_AllOccurrences);

    }


    void OnImportClose (x_Code) override

    {

        AllLines.Clear();  // Free up the memory.

        NextLine = 0;

    }


    int            NextLine = 0;

    tsc_StringList AllLines;

};