<commit_before>#include "GUI.hpp"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QDir>
#include <QLabel>
#include <QImage>
#include <QInputDialog>
#include <FAST/Visualization/ImageRenderer/ImageRenderer.hpp>
#include <FAST/Visualization/TextRenderer/TextRenderer.hpp>
#include <FAST/Streamers/ImageFileStreamer.hpp>
#include <QMessageBox>
#include <QElapsedTimer>
#include <QComboBox>
#include <QDesktopServices>
#include <QListWidget>
#include <QFileDialog>
#include <QInputDialog>
#include <FAST/PipelineEditor.hpp>
#include <fstream>
#include <QDesktopWidget>
#include <QApplication>

#include <QProxyStyle>

// Used to fix direct jump for QSlider
class MyStyle : public QProxyStyle {
    public:
        using QProxyStyle::QProxyStyle;

        int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0, const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const {
            if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
                return (Qt::LeftButton | Qt::MidButton | Qt::RightButton);
            return QProxyStyle::styleHint(hint, option, widget, returnData);
        }
};

namespace fast {

GUI::GUI() {
    mStreamingMode = STREAMING_MODE_STORE_ALL_FRAMES;
    QDesktopWidget* desktop = QApplication::desktop();
    menuWidth = desktop->width()*(1.0f/6.0f);
    mPipelineWidget = nullptr;
    mStreamer = ImageFileStreamer::New();

    QVBoxLayout* viewLayout = new QVBoxLayout;

    View* view = createView();
    view->set2DMode();
    view->setBackgroundColor(Color::Black());
    setWidth(desktop->width());
    setHeight(desktop->height());
    enableMaximized();
    setTitle("FAST - Viewer");
    viewLayout->addWidget(view);

    menuLayout = new QVBoxLayout;
    menuLayout->setAlignment(Qt::AlignTop);

    // Logo
    QImage* image = new QImage;
    image->load((Config::getDocumentationPath() + "images/FAST_logo_square.png").c_str());
    QLabel* logo = new QLabel;
    logo->setPixmap(QPixmap::fromImage(image->scaled(menuWidth, ((float)menuWidth/image->width())*image->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)));
    logo->adjustSize();
    menuLayout->addWidget(logo);

    // Title label
    QLabel* title = new QLabel;
    title->setText("Viewer");
	QFont font;
	font.setPixelSize(24 * getScalingFactor());
	font.setWeight(QFont::Bold);
	title->setFont(font);
	title->setAlignment(Qt::AlignCenter);
    menuLayout->addWidget(title);

    // Quit button
    QPushButton* quitButton = new QPushButton;
    quitButton->setText("Quit (q)");
    quitButton->setStyleSheet("QPushButton { background-color: red; color: white; }");
    quitButton->setFixedWidth(menuWidth);
    menuLayout->addWidget(quitButton);

    // Connect the clicked signal of the quit button to the stop method for the window
    QObject::connect(quitButton, &QPushButton::clicked, std::bind(&Window::stop, this));

    QLabel* inputListLabel = new QLabel;
    //inputListLabel->setFixedHeight(24);
    inputListLabel->setText("Input data");
    inputListLabel->setStyleSheet("QLabel { font-weight: bold; }");
    menuLayout->addWidget(inputListLabel);

    mList = new QListWidget;
    mList->setFixedWidth(menuWidth);
    mList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    mList->setFixedHeight(200);
    mList->setSelectionMode(QAbstractItemView::ExtendedSelection); // Allow multiple items to be selected
    QObject::connect(mList, &QListWidget::itemSelectionChanged, std::bind(&GUI::selectInputData, this));
    menuLayout->addWidget(mList);

    QPushButton* addButton = new QPushButton;
    addButton->setText("Add input data");
    addButton->setFixedWidth(menuWidth);
    QObject::connect(addButton, &QPushButton::clicked, std::bind(&GUI::addInputData, this));
    menuLayout->addWidget(addButton);

    QLabel* selectPipelineLabel = new QLabel;
    selectPipelineLabel->setText("Active pipeline");
    selectPipelineLabel->setStyleSheet("QLabel { font-weight: bold; }");
    //selectPipelineLabel->setFixedHeight(24);
    menuLayout->addWidget(selectPipelineLabel);

    mSelectPipeline = new QComboBox;
    mSelectPipeline->setFixedWidth(menuWidth);
    mPipelines = getAvailablePipelines();
    int index = 0;
    int counter = 0;
    for(auto pipeline : mPipelines) {
        mSelectPipeline->addItem((pipeline.getName() + " (" + pipeline.getDescription() + ")").c_str());
        if(pipeline.getName() == "Image renderer") {
            index = counter;
        }
        ++counter;
    }
    mSelectPipeline->setCurrentIndex(index);

    menuLayout->addWidget(mSelectPipeline);
    QObject::connect(mSelectPipeline, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), std::bind(&GUI::selectPipeline, this));

    QPushButton* refreshPipeline = new QPushButton;
    refreshPipeline->setText("Refresh pipeline");
    refreshPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }");
    refreshPipeline->setFixedWidth(menuWidth);
    QObject::connect(refreshPipeline, &QPushButton::clicked, std::bind(&GUI::selectPipeline, this));
    menuLayout->addWidget(refreshPipeline);

    QPushButton* editPipeline = new QPushButton;
    editPipeline->setText("Edit pipeline");
    editPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }");
    editPipeline->setFixedWidth(menuWidth);
    QObject::connect(editPipeline, &QPushButton::clicked, std::bind(&GUI::editPipeline, this));
    menuLayout->addWidget(editPipeline);

    QPushButton* newPipeline = new QPushButton;
    newPipeline->setText("New pipeline");
    newPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }");
    newPipeline->setFixedWidth(menuWidth);
    QObject::connect(newPipeline, &QPushButton::clicked, std::bind(&GUI::newPipeline, this));
    menuLayout->addWidget(newPipeline);

    // Playback
    QHBoxLayout* playbackLayout = new QHBoxLayout;

    mPlayPauseButton = new QPushButton;
    mPlayPauseButton->setText("Play");
    mPlayPauseButton->setStyleSheet("QPushButton { background-color: green; color: white; }");
    //mPlayPauseButton->setFixedHeight(100);
    QObject::connect(mPlayPauseButton, &QPushButton::clicked, std::bind(&GUI::playPause, this));
    playbackLayout->addWidget(mPlayPauseButton);

    mTimestepSlider = new QSlider(Qt::Horizontal);
    // Improve style of slider
    mTimestepSlider->setStyleSheet("QSlider:horizontal { min-height: 50px; } QSlider::groove:horizontal {\n"
                                           "    border: 1px solid #999999;\n"
                                           "    height: 10px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */\n"
                                           "    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);\n"
                                           "    margin: 2px 0;\n"
                                           "}\n"
                                           "\n"
                                           "QSlider::handle:horizontal {\n"
                                           "    background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #81BEF7, stop:1 #2E9AFE);\n"
                                           "    border: 1px solid #5c5c5c;\n"
                                           "    width: 18px;\n"
                                           "    height: 25px;\n"
                                           "    margin: -10px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */\n"
                                           "    border-radius: 3px;\n"
                                           "}");
    playbackLayout->addWidget(mTimestepSlider);
    mTimestepSlider->setTickPosition(QSlider::NoTicks);
    mTimestepSlider->setRange(0, 1234);
    mTimestepSlider->setPageStep(1);
    mTimestepSlider->setSingleStep(1);
    mTimestepSlider->setStyle(new MyStyle(mTimestepSlider->style())); // Fixes issues with direct jump with slider
    QObject::connect(mTimestepSlider, &QSlider::sliderMoved, std::bind(&GUI::setTimestep, this));
    QObject::connect(mTimestepSlider, &QSlider::sliderPressed, std::bind(&GUI::setTimestep, this));

    viewLayout->addLayout(playbackLayout);

    // Add menu and view to main layout
    QHBoxLayout* layout = new QHBoxLayout;
    layout->addLayout(menuLayout);
    layout->addLayout(viewLayout);

    mWidget->setLayout(layout);
	std::cout << "Finished viewer setup" << std::endl;

}

void GUI::newPipeline() {
    bool ok;
    QString text = QInputDialog::getText(mWidget, "Create new pipeline", "Enter filename of new pipeline:", QLineEdit::Normal, "", &ok);

    if(ok && !text.isEmpty()) {
        std::string filename = (const char*)text.toUtf8();
        // Make sure file ends with .fpl
        if(filename.substr(filename.size() - 3) != "fpl")
            filename += ".fpl";

        // Create pipeline file with template
        std::ofstream file(Config::getPipelinePath() + filename);
        file << "# New pipeline template\n"
         "PipelineName \"<Pipeline name here>\"\n"
        "PipelineDescription \"<Pipeline description here>\"\n\n"

        "# Pipeline needs at least 1 renderer\n"
        "Renderer renderer ImageRenderer\n"
        "Input 0 PipelineInput\n"
        "Attribute window 255\n"
        "Attribute level 127.5\n";
        file.close();

        PipelineEditor *editor = new PipelineEditor(filename);
        QObject::connect(editor, &PipelineEditor::saved, std::bind(&GUI::selectPipeline, this));
        editor->show();
    }
}

void GUI::editPipeline() {
    int selectedPipeline = mSelectPipeline->currentIndex();
    Pipeline pipeline = mPipelines.at(selectedPipeline);
    PipelineEditor* editor = new PipelineEditor(pipeline.getFilename());
    QObject::connect(editor, &PipelineEditor::saved, std::bind(&GUI::selectPipeline, this));
    editor->show();
}

void GUI::selectPipeline() {
    // Stop computation thread before removing renderers
    stopComputationThread();

    std::vector<std::string> inputData;
    for(QListWidgetItem* widget : mList->selectedItems()) {
		std::string asd = widget->text().toUtf8().constData();
        inputData.push_back(asd);
    }
    mStreamer = ImageFileStreamer::New();
    mStreamer->setFilenameFormats(inputData);

    // Preload the data
    DataPort::pointer data = mStreamer->getOutputPort();
    int timestep = 0;
    mStreamer->update(0, STREAMING_MODE_STORE_ALL_FRAMES);
    while(!mStreamer->hasReachedEnd()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    getView(0)->removeAllRenderers();

    int selectedPipeline = mSelectPipeline->currentIndex();
    Pipeline pipeline = mPipelines.at(selectedPipeline);
    try {
        std::vector<SharedPointer<Renderer>> renderers = pipeline.setup(data);
        for(auto renderer : renderers) {
            // A hack for text renderer which needs a reference to the view
            if(renderer->getNameOfClass() == "TextRenderer") {
                TextRenderer::pointer textRenderer = renderer;
                textRenderer->setView(getView(0));
            }
            getView(0)->addRenderer(renderer);
        }
        getView(0)->reinitialize();
    } catch(Exception &e) {
        QMessageBox* message = new QMessageBox;
        message->setWindowTitle("Error");
        message->setText(e.what());
        message->show();
    }

    startComputationThread();
    mPlayPauseButton->setText("Pause");
    mPlayPauseButton->setStyleSheet("QPushButton { background-color: red; color: white; }");
    mThread->setTimestepLimit(data->getSize());
    mTimestepSlider->setRange(0, data->getSize() - 1);
    mThread->setTimestepLoop(true);
    QObject::connect(mThread, &ComputationThread::timestepIncreased, std::bind(&GUI::increaseTimestep, this));
    /*
    PipelineWidget* pipelineWidget = new PipelineWidget(pipeline, mWidget);
    pipelineWidget->setFixedWidth(menuWidth);
    if(mPipelineWidget == nullptr) {
        menuLayout->addWidget(pipelineWidget);
    } else {
        menuLayout->replaceWidget(mPipelineWidget, pipelineWidget);
    }
    mPipelineWidget = pipelineWidget;
     */
}

void GUI::increaseTimestep() {
    mTimestepSlider->setSliderPosition(mThread->getTimestep());
}

void GUI::setTimestep() {
    mThread->pause();
    mPlayPauseButton->setText("Play");
    mPlayPauseButton->setStyleSheet("QPushButton { background-color: green; color: white; }");
    mThread->setTimestep(mTimestepSlider->sliderPosition());
    for(auto renderer : getView(0)->getRenderers()) {
        renderer->setModified(true);
    }
}

void GUI::selectInputData() {
    selectPipeline();
}

void GUI::addInputData() {
    QFileDialog fileDialog(mWidget);
    fileDialog.setNameFilter("Image recordings (*_0.mhd *_0.png *_0.jpg *_0.bmp)");
    QStringList filenames;
    if(fileDialog.exec()) {
        filenames = fileDialog.selectedFiles();
        for(QString qfilename : filenames) {
			std::string filename = qfilename.toUtf8().constData();
            filename = replace(filename, "_0.", "_#.");
            mList->addItem(filename.c_str());
        }
    }
}

void GUI::playPause() {
    if(mPlayPauseButton->text() == "Play") {
        mThread->resume();
        mPlayPauseButton->setText("Pause");
        mPlayPauseButton->setStyleSheet("QPushButton { background-color: red; color: white; }");
    } else {
        mThread->pause();
        mPlayPauseButton->setText("Play");
        mPlayPauseButton->setStyleSheet("QPushButton { background-color: green; color: white; }");
    }
}

}
<commit_msg>Removed unused variable<commit_after>#include "GUI.hpp"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QDir>
#include <QLabel>
#include <QImage>
#include <QInputDialog>
#include <FAST/Visualization/ImageRenderer/ImageRenderer.hpp>
#include <FAST/Visualization/TextRenderer/TextRenderer.hpp>
#include <FAST/Streamers/ImageFileStreamer.hpp>
#include <QMessageBox>
#include <QElapsedTimer>
#include <QComboBox>
#include <QDesktopServices>
#include <QListWidget>
#include <QFileDialog>
#include <QInputDialog>
#include <FAST/PipelineEditor.hpp>
#include <fstream>
#include <QDesktopWidget>
#include <QApplication>

#include <QProxyStyle>

// Used to fix direct jump for QSlider
class MyStyle : public QProxyStyle {
    public:
        using QProxyStyle::QProxyStyle;

        int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0, const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const {
            if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
                return (Qt::LeftButton | Qt::MidButton | Qt::RightButton);
            return QProxyStyle::styleHint(hint, option, widget, returnData);
        }
};

namespace fast {

GUI::GUI() {
    mStreamingMode = STREAMING_MODE_STORE_ALL_FRAMES;
    QDesktopWidget* desktop = QApplication::desktop();
    menuWidth = desktop->width()*(1.0f/6.0f);
    mPipelineWidget = nullptr;
    mStreamer = ImageFileStreamer::New();

    QVBoxLayout* viewLayout = new QVBoxLayout;

    View* view = createView();
    view->set2DMode();
    view->setBackgroundColor(Color::Black());
    setWidth(desktop->width());
    setHeight(desktop->height());
    enableMaximized();
    setTitle("FAST - Viewer");
    viewLayout->addWidget(view);

    menuLayout = new QVBoxLayout;
    menuLayout->setAlignment(Qt::AlignTop);

    // Logo
    QImage* image = new QImage;
    image->load((Config::getDocumentationPath() + "images/FAST_logo_square.png").c_str());
    QLabel* logo = new QLabel;
    logo->setPixmap(QPixmap::fromImage(image->scaled(menuWidth, ((float)menuWidth/image->width())*image->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation)));
    logo->adjustSize();
    menuLayout->addWidget(logo);

    // Title label
    QLabel* title = new QLabel;
    title->setText("Viewer");
	QFont font;
	font.setPixelSize(24 * getScalingFactor());
	font.setWeight(QFont::Bold);
	title->setFont(font);
	title->setAlignment(Qt::AlignCenter);
    menuLayout->addWidget(title);

    // Quit button
    QPushButton* quitButton = new QPushButton;
    quitButton->setText("Quit (q)");
    quitButton->setStyleSheet("QPushButton { background-color: red; color: white; }");
    quitButton->setFixedWidth(menuWidth);
    menuLayout->addWidget(quitButton);

    // Connect the clicked signal of the quit button to the stop method for the window
    QObject::connect(quitButton, &QPushButton::clicked, std::bind(&Window::stop, this));

    QLabel* inputListLabel = new QLabel;
    //inputListLabel->setFixedHeight(24);
    inputListLabel->setText("Input data");
    inputListLabel->setStyleSheet("QLabel { font-weight: bold; }");
    menuLayout->addWidget(inputListLabel);

    mList = new QListWidget;
    mList->setFixedWidth(menuWidth);
    mList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
    mList->setFixedHeight(200);
    mList->setSelectionMode(QAbstractItemView::ExtendedSelection); // Allow multiple items to be selected
    QObject::connect(mList, &QListWidget::itemSelectionChanged, std::bind(&GUI::selectInputData, this));
    menuLayout->addWidget(mList);

    QPushButton* addButton = new QPushButton;
    addButton->setText("Add input data");
    addButton->setFixedWidth(menuWidth);
    QObject::connect(addButton, &QPushButton::clicked, std::bind(&GUI::addInputData, this));
    menuLayout->addWidget(addButton);

    QLabel* selectPipelineLabel = new QLabel;
    selectPipelineLabel->setText("Active pipeline");
    selectPipelineLabel->setStyleSheet("QLabel { font-weight: bold; }");
    //selectPipelineLabel->setFixedHeight(24);
    menuLayout->addWidget(selectPipelineLabel);

    mSelectPipeline = new QComboBox;
    mSelectPipeline->setFixedWidth(menuWidth);
    mPipelines = getAvailablePipelines();
    int index = 0;
    int counter = 0;
    for(auto pipeline : mPipelines) {
        mSelectPipeline->addItem((pipeline.getName() + " (" + pipeline.getDescription() + ")").c_str());
        if(pipeline.getName() == "Image renderer") {
            index = counter;
        }
        ++counter;
    }
    mSelectPipeline->setCurrentIndex(index);

    menuLayout->addWidget(mSelectPipeline);
    QObject::connect(mSelectPipeline, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), std::bind(&GUI::selectPipeline, this));

    QPushButton* refreshPipeline = new QPushButton;
    refreshPipeline->setText("Refresh pipeline");
    refreshPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }");
    refreshPipeline->setFixedWidth(menuWidth);
    QObject::connect(refreshPipeline, &QPushButton::clicked, std::bind(&GUI::selectPipeline, this));
    menuLayout->addWidget(refreshPipeline);

    QPushButton* editPipeline = new QPushButton;
    editPipeline->setText("Edit pipeline");
    editPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }");
    editPipeline->setFixedWidth(menuWidth);
    QObject::connect(editPipeline, &QPushButton::clicked, std::bind(&GUI::editPipeline, this));
    menuLayout->addWidget(editPipeline);

    QPushButton* newPipeline = new QPushButton;
    newPipeline->setText("New pipeline");
    newPipeline->setStyleSheet("QPushButton { background-color: blue; color: white; }");
    newPipeline->setFixedWidth(menuWidth);
    QObject::connect(newPipeline, &QPushButton::clicked, std::bind(&GUI::newPipeline, this));
    menuLayout->addWidget(newPipeline);

    // Playback
    QHBoxLayout* playbackLayout = new QHBoxLayout;

    mPlayPauseButton = new QPushButton;
    mPlayPauseButton->setText("Play");
    mPlayPauseButton->setStyleSheet("QPushButton { background-color: green; color: white; }");
    //mPlayPauseButton->setFixedHeight(100);
    QObject::connect(mPlayPauseButton, &QPushButton::clicked, std::bind(&GUI::playPause, this));
    playbackLayout->addWidget(mPlayPauseButton);

    mTimestepSlider = new QSlider(Qt::Horizontal);
    // Improve style of slider
    mTimestepSlider->setStyleSheet("QSlider:horizontal { min-height: 50px; } QSlider::groove:horizontal {\n"
                                           "    border: 1px solid #999999;\n"
                                           "    height: 10px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */\n"
                                           "    background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);\n"
                                           "    margin: 2px 0;\n"
                                           "}\n"
                                           "\n"
                                           "QSlider::handle:horizontal {\n"
                                           "    background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #81BEF7, stop:1 #2E9AFE);\n"
                                           "    border: 1px solid #5c5c5c;\n"
                                           "    width: 18px;\n"
                                           "    height: 25px;\n"
                                           "    margin: -10px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */\n"
                                           "    border-radius: 3px;\n"
                                           "}");
    playbackLayout->addWidget(mTimestepSlider);
    mTimestepSlider->setTickPosition(QSlider::NoTicks);
    mTimestepSlider->setRange(0, 1234);
    mTimestepSlider->setPageStep(1);
    mTimestepSlider->setSingleStep(1);
    mTimestepSlider->setStyle(new MyStyle(mTimestepSlider->style())); // Fixes issues with direct jump with slider
    QObject::connect(mTimestepSlider, &QSlider::sliderMoved, std::bind(&GUI::setTimestep, this));
    QObject::connect(mTimestepSlider, &QSlider::sliderPressed, std::bind(&GUI::setTimestep, this));

    viewLayout->addLayout(playbackLayout);

    // Add menu and view to main layout
    QHBoxLayout* layout = new QHBoxLayout;
    layout->addLayout(menuLayout);
    layout->addLayout(viewLayout);

    mWidget->setLayout(layout);
	std::cout << "Finished viewer setup" << std::endl;

}

void GUI::newPipeline() {
    bool ok;
    QString text = QInputDialog::getText(mWidget, "Create new pipeline", "Enter filename of new pipeline:", QLineEdit::Normal, "", &ok);

    if(ok && !text.isEmpty()) {
        std::string filename = (const char*)text.toUtf8();
        // Make sure file ends with .fpl
        if(filename.substr(filename.size() - 3) != "fpl")
            filename += ".fpl";

        // Create pipeline file with template
        std::ofstream file(Config::getPipelinePath() + filename);
        file << "# New pipeline template\n"
         "PipelineName \"<Pipeline name here>\"\n"
        "PipelineDescription \"<Pipeline description here>\"\n\n"

        "# Pipeline needs at least 1 renderer\n"
        "Renderer renderer ImageRenderer\n"
        "Input 0 PipelineInput\n"
        "Attribute window 255\n"
        "Attribute level 127.5\n";
        file.close();

        PipelineEditor *editor = new PipelineEditor(filename);
        QObject::connect(editor, &PipelineEditor::saved, std::bind(&GUI::selectPipeline, this));
        editor->show();
    }
}

void GUI::editPipeline() {
    int selectedPipeline = mSelectPipeline->currentIndex();
    Pipeline pipeline = mPipelines.at(selectedPipeline);
    PipelineEditor* editor = new PipelineEditor(pipeline.getFilename());
    QObject::connect(editor, &PipelineEditor::saved, std::bind(&GUI::selectPipeline, this));
    editor->show();
}

void GUI::selectPipeline() {
    // Stop computation thread before removing renderers
    stopComputationThread();

    std::vector<std::string> inputData;
    for(QListWidgetItem* widget : mList->selectedItems()) {
		std::string asd = widget->text().toUtf8().constData();
        inputData.push_back(asd);
    }
    mStreamer = ImageFileStreamer::New();
    mStreamer->setFilenameFormats(inputData);

    // Preload the data
    DataPort::pointer data = mStreamer->getOutputPort();
    mStreamer->update(0, STREAMING_MODE_STORE_ALL_FRAMES);
    while(!mStreamer->hasReachedEnd()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    getView(0)->removeAllRenderers();

    int selectedPipeline = mSelectPipeline->currentIndex();
    Pipeline pipeline = mPipelines.at(selectedPipeline);
    try {
        std::vector<SharedPointer<Renderer>> renderers = pipeline.setup(data);
        for(auto renderer : renderers) {
            // A hack for text renderer which needs a reference to the view
            if(renderer->getNameOfClass() == "TextRenderer") {
                TextRenderer::pointer textRenderer = renderer;
                textRenderer->setView(getView(0));
            }
            getView(0)->addRenderer(renderer);
        }
        getView(0)->reinitialize();
    } catch(Exception &e) {
        QMessageBox* message = new QMessageBox;
        message->setWindowTitle("Error");
        message->setText(e.what());
        message->show();
    }

    startComputationThread();
    mPlayPauseButton->setText("Pause");
    mPlayPauseButton->setStyleSheet("QPushButton { background-color: red; color: white; }");
    mThread->setTimestepLimit(data->getSize());
    mTimestepSlider->setRange(0, data->getSize() - 1);
    mThread->setTimestepLoop(true);
    QObject::connect(mThread, &ComputationThread::timestepIncreased, std::bind(&GUI::increaseTimestep, this));
    /*
    PipelineWidget* pipelineWidget = new PipelineWidget(pipeline, mWidget);
    pipelineWidget->setFixedWidth(menuWidth);
    if(mPipelineWidget == nullptr) {
        menuLayout->addWidget(pipelineWidget);
    } else {
        menuLayout->replaceWidget(mPipelineWidget, pipelineWidget);
    }
    mPipelineWidget = pipelineWidget;
     */
}

void GUI::increaseTimestep() {
    mTimestepSlider->setSliderPosition(mThread->getTimestep());
}

void GUI::setTimestep() {
    mThread->pause();
    mPlayPauseButton->setText("Play");
    mPlayPauseButton->setStyleSheet("QPushButton { background-color: green; color: white; }");
    mThread->setTimestep(mTimestepSlider->sliderPosition());
    for(auto renderer : getView(0)->getRenderers()) {
        renderer->setModified(true);
    }
}

void GUI::selectInputData() {
    selectPipeline();
}

void GUI::addInputData() {
    QFileDialog fileDialog(mWidget);
    fileDialog.setNameFilter("Image recordings (*_0.mhd *_0.png *_0.jpg *_0.bmp)");
    QStringList filenames;
    if(fileDialog.exec()) {
        filenames = fileDialog.selectedFiles();
        for(QString qfilename : filenames) {
			std::string filename = qfilename.toUtf8().constData();
            filename = replace(filename, "_0.", "_#.");
            mList->addItem(filename.c_str());
        }
    }
}

void GUI::playPause() {
    if(mPlayPauseButton->text() == "Play") {
        mThread->resume();
        mPlayPauseButton->setText("Pause");
        mPlayPauseButton->setStyleSheet("QPushButton { background-color: red; color: white; }");
    } else {
        mThread->pause();
        mPlayPauseButton->setText("Play");
        mPlayPauseButton->setStyleSheet("QPushButton { background-color: green; color: white; }");
    }
}

}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: collect.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: kz $ $Date: 2006-07-21 11:22:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

#include <string.h>

#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#ifndef _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX
#include <unotools/transliterationwrapper.hxx>
#endif

#include "rechead.hxx"
#include "collect.hxx"
#include "document.hxx"         // fuer TypedStrData Konstruktor

// -----------------------------------------------------------------------

DataObject::~DataObject()
{
}

//------------------------------------------------------------------------
// Collection
//------------------------------------------------------------------------

void lcl_DeleteDataObjects( DataObject** p, USHORT nCount )
{
    if ( p )
    {
        for (USHORT i = 0; i < nCount; i++) delete p[i];
        delete[] p;
        p = NULL;
    }
}

Collection::Collection(USHORT nLim, USHORT nDel) :
    nCount ( 0 ),
    nLimit ( nLim ),
    nDelta ( nDel ),
    pItems ( NULL )
{
    if (nDelta > MAXDELTA)
        nDelta = MAXDELTA;
    else if (nDelta == 0)
        nDelta = 1;
    if (nLimit > MAXCOLLECTIONSIZE)
        nLimit = MAXCOLLECTIONSIZE;
    else if (nLimit < nDelta)
        nLimit = nDelta;
    pItems = new DataObject*[nLimit];
}

Collection::Collection(const Collection& rCollection)
    :   nCount ( 0 ),
        nLimit ( 0 ),
        nDelta ( 0 ),
        pItems ( NULL )
{
    *this = rCollection;
}

//------------------------------------------------------------------------

Collection::~Collection()
{
    lcl_DeleteDataObjects( pItems, nCount );
}

//------------------------------------------------------------------------

void Collection::AtFree(USHORT nIndex)
{
    if ((pItems) && (nIndex < nCount))
    {
        delete pItems[nIndex];
        --nCount;               // before memmove
        memmove ( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(DataObject*));
        pItems[nCount] = NULL;
    }
}

//------------------------------------------------------------------------

void Collection::Free(DataObject* pDataObject)
{
    AtFree(IndexOf(pDataObject));
}

//------------------------------------------------------------------------

void Collection::FreeAll()
{
    lcl_DeleteDataObjects( pItems, nCount );
    nCount = 0;
    pItems = new DataObject*[nLimit];
}

//------------------------------------------------------------------------

BOOL Collection::AtInsert(USHORT nIndex, DataObject* pDataObject)
{
    if ((nCount < MAXCOLLECTIONSIZE) && (nIndex <= nCount) && pItems)
    {
        if (nCount == nLimit)
        {
            DataObject** pNewItems = new DataObject*[nLimit + nDelta];
            if (!pNewItems)
                return FALSE;
            nLimit += nDelta;
            memmove(pNewItems, pItems, nCount * sizeof(DataObject*));
            delete[] pItems;
            pItems = pNewItems;
        }
        if (nCount > nIndex)
            memmove(&pItems[nIndex + 1], &pItems[nIndex], (nCount - nIndex) * sizeof(DataObject*));
        pItems[nIndex] = pDataObject;
        nCount++;
        return TRUE;
    }
    return FALSE;
}

//------------------------------------------------------------------------

BOOL Collection::Insert(DataObject* pDataObject)
{
    return AtInsert(nCount, pDataObject);
}

//------------------------------------------------------------------------

DataObject* Collection::At(USHORT nIndex) const
{
    if (nIndex < nCount)
        return pItems[nIndex];
    else
        return NULL;
}

//------------------------------------------------------------------------

USHORT Collection::IndexOf(DataObject* pDataObject) const
{
    USHORT nIndex = 0xffff;
    for (USHORT i = 0; ((i < nCount) && (nIndex == 0xffff)); i++)
    {
        if (pItems[i] == pDataObject) nIndex = i;
    }
    return nIndex;
}

//------------------------------------------------------------------------

Collection& Collection::operator=( const Collection& r )
{
    lcl_DeleteDataObjects( pItems, nCount );

    nCount = r.nCount;
    nLimit = r.nLimit;
    nDelta = r.nDelta;
    pItems = new DataObject*[nLimit];
    for ( USHORT i=0; i<nCount; i++ )
        pItems[i] = r.pItems[i]->Clone();

    return *this;
}

//------------------------------------------------------------------------

DataObject* Collection::Clone() const
{
    return new Collection(*this);
}

//------------------------------------------------------------------------
// SortedCollection
//------------------------------------------------------------------------

SortedCollection::SortedCollection(USHORT nLim, USHORT nDel, BOOL bDup) :
    Collection (nLim, nDel),
    bDuplicates ( bDup)
{
}

//------------------------------------------------------------------------

USHORT SortedCollection::IndexOf(DataObject* pDataObject) const
{
    USHORT nIndex;
    if (Search(pDataObject, nIndex))
        return nIndex;
    else
        return 0xffff;
}

//------------------------------------------------------------------------

BOOL SortedCollection::Search(DataObject* pDataObject, USHORT& rIndex) const
{
    rIndex = nCount;
    BOOL bFound = FALSE;
    short nLo = 0;
    short nHi = nCount - 1;
    short nIndex;
    short nCompare;
    while (nLo <= nHi)
    {
        nIndex = (nLo + nHi) / 2;
        nCompare = Compare(pItems[nIndex], pDataObject);
        if (nCompare < 0)
            nLo = nIndex + 1;
        else
        {
            nHi = nIndex - 1;
            if (nCompare == 0)
            {
                bFound = TRUE;
                nLo = nIndex;
            }
        }
    }
    rIndex = nLo;
    return bFound;
}

//------------------------------------------------------------------------

BOOL SortedCollection::Insert(DataObject* pDataObject)
{
    USHORT nIndex;
    BOOL bFound = Search(pDataObject, nIndex);
    if (bFound)
    {
        if (bDuplicates)
            return AtInsert(nIndex, pDataObject);
        else
            return FALSE;
    }
    else
        return AtInsert(nIndex, pDataObject);
}

//------------------------------------------------------------------------

BOOL SortedCollection::InsertPos(DataObject* pDataObject, USHORT& nIndex)
{
    BOOL bFound = Search(pDataObject, nIndex);
    if (bFound)
    {
        if (bDuplicates)
            return AtInsert(nIndex, pDataObject);
        else
            return FALSE;
    }
    else
        return AtInsert(nIndex, pDataObject);
}

//------------------------------------------------------------------------

BOOL SortedCollection::operator==(const SortedCollection& rCmp) const
{
    if ( nCount != rCmp.nCount )
        return FALSE;
    for (USHORT i=0; i<nCount; i++)
        if ( !IsEqual(pItems[i],rCmp.pItems[i]) )
            return FALSE;
    return TRUE;
}

//------------------------------------------------------------------------

//  IsEqual - komplette Inhalte vergleichen

BOOL SortedCollection::IsEqual(DataObject* pKey1, DataObject* pKey2) const
{
    return ( Compare(pKey1, pKey2) == 0 );      // Default: nur Index vergleichen
}

//------------------------------------------------------------------------

DataObject* StrData::Clone() const
{
    return new StrData(*this);
}

//------------------------------------------------------------------------

short StrCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
{
    StringCompare eComp = ((StrData*)pKey1)->aStr.CompareTo(((StrData*)pKey2)->aStr);
    if (eComp == COMPARE_EQUAL)
        return 0;
    else if (eComp == COMPARE_LESS)
        return -1;
    else
        return 1;
}

//------------------------------------------------------------------------

DataObject* StrCollection::Clone() const
{
    return new StrCollection(*this);
}

//------------------------------------------------------------------------

void StrCollection::Load( SvStream& rStream )
{
    ScReadHeader aHdr( rStream );
    lcl_DeleteDataObjects( pItems, nCount );
    BOOL bDups;
    rStream >> bDups;
    SetDups( bDups );
    rStream >> nCount >> nLimit >> nDelta;
    pItems = new DataObject*[nLimit];
    String aStr;
    rtl_TextEncoding eSet = rStream.GetStreamCharSet();
    for ( USHORT i=0; i<nCount; i++ )
    {
        rStream.ReadByteString( aStr, eSet );
        pItems[i] = new StrData( aStr );
    }
}

void StrCollection::Store( SvStream& rStream ) const
{
    ScWriteHeader aHdr( rStream );
    BOOL bDups = IsDups();
    rStream << bDups << nCount << nLimit << nDelta;
    rtl_TextEncoding eSet = rStream.GetStreamCharSet();
    for ( USHORT i=0; i<nCount; i++ )
    {
        rStream.WriteByteString( ((StrData*)pItems[i])->GetString(), eSet );
    }
}

//------------------------------------------------------------------------
// TypedStrCollection
//------------------------------------------------------------------------

TypedStrData::TypedStrData( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
                                BOOL bAllStrings )
{
    if ( pDoc->HasValueData( nCol, nRow, nTab ) )
    {
        pDoc->GetValue( nCol, nRow, nTab, nValue );
        if (bAllStrings)
            pDoc->GetString( nCol, nRow, nTab, aStrValue );
        nStrType = 0;
    }
    else
    {
        pDoc->GetString( nCol, nRow, nTab, aStrValue );
        nValue = 0.0;
        nStrType = 1;       //! Typ uebergeben ?
    }
}

DataObject* TypedStrData::Clone() const
{
    return new TypedStrData(*this);
}

DataObject* TypedStrCollection::Clone() const
{
    return new TypedStrCollection(*this);
}

short TypedStrCollection::Compare( DataObject* pKey1, DataObject* pKey2 ) const
{
    short nResult = 0;

    if ( pKey1 && pKey2 )
    {
        TypedStrData& rData1 = (TypedStrData&)*pKey1;
        TypedStrData& rData2 = (TypedStrData&)*pKey2;

        if ( rData1.nStrType > rData2.nStrType )
            nResult = 1;
        else if ( rData1.nStrType < rData2.nStrType )
            nResult = -1;
        else if ( !rData1.nStrType /* && !rData2.nStrType */ )
        {
            //--------------------
            // Zahlen vergleichen:
            //--------------------
            if ( rData1.nValue == rData2.nValue )
                nResult = 0;
            else if ( rData1.nValue < rData2.nValue )
                nResult = -1;
            else
                nResult = 1;
        }
        else /* if ( rData1.nStrType && rData2.nStrType ) */
        {
            //---------------------
            // Strings vergleichen:
            //---------------------
            if ( bCaseSensitive )
                nResult = (short) ScGlobal::pCaseTransliteration->compareString(
                    rData1.aStrValue, rData2.aStrValue );
            else
                nResult = (short) ScGlobal::pTransliteration->compareString(
                    rData1.aStrValue, rData2.aStrValue );
        }
    }

    return nResult;
}

BOOL TypedStrCollection::FindText( const String& rStart, String& rResult,
                                    USHORT& rPos, BOOL bBack ) const
{
    //  Die Collection ist nach String-Vergleichen sortiert, darum muss hier
    //  alles durchsucht werden

    BOOL bFound = FALSE;

    String aOldResult;
    if ( rPos != SCPOS_INVALID && rPos < nCount )
    {
        TypedStrData* pData = (TypedStrData*) pItems[rPos];
        if (pData->nStrType)
            aOldResult = pData->aStrValue;
    }

    if ( bBack )                                    // rueckwaerts
    {
        USHORT nStartPos = nCount;
        if ( rPos != SCPOS_INVALID )
            nStartPos = rPos;                       // weitersuchen...

        for ( USHORT i=nStartPos; i>0; )
        {
            --i;
            TypedStrData* pData = (TypedStrData*) pItems[i];
            if (pData->nStrType)
            {
                if ( ScGlobal::pTransliteration->isMatch( rStart, pData->aStrValue ) )
                {
                    //  If the collection is case sensitive, it may contain several entries
                    //  that are equal when compared case-insensitive. They are skipped here.
                    if ( !bCaseSensitive || !aOldResult.Len() ||
                            !ScGlobal::pTransliteration->isEqual(
                            pData->aStrValue, aOldResult ) )
                    {
                        rResult = pData->aStrValue;
                        rPos = i;
                        bFound = TRUE;
                        break;
                    }
                }
            }
        }
    }
    else                                            // vorwaerts
    {
        USHORT nStartPos = 0;
        if ( rPos != SCPOS_INVALID )
            nStartPos = rPos + 1;                   // weitersuchen...

        for ( USHORT i=nStartPos; i<nCount; i++ )
        {
            TypedStrData* pData = (TypedStrData*) pItems[i];
            if (pData->nStrType)
            {
                if ( ScGlobal::pTransliteration->isMatch( rStart, pData->aStrValue ) )
                {
                    //  If the collection is case sensitive, it may contain several entries
                    //  that are equal when compared case-insensitive. They are skipped here.
                    if ( !bCaseSensitive || !aOldResult.Len() ||
                            !ScGlobal::pTransliteration->isEqual(
                            pData->aStrValue, aOldResult ) )
                    {
                        rResult = pData->aStrValue;
                        rPos = i;
                        bFound = TRUE;
                        break;
                    }
                }
            }
        }
    }

    return bFound;
}

        // Gross-/Kleinschreibung anpassen

BOOL TypedStrCollection::GetExactMatch( String& rString ) const
{
    for (USHORT i=0; i<nCount; i++)
    {
        TypedStrData* pData = (TypedStrData*) pItems[i];
        if ( pData->nStrType && ScGlobal::pTransliteration->isEqual(
                pData->aStrValue, rString ) )
        {
            rString = pData->aStrValue;                         // String anpassen
            return TRUE;
        }
    }

    return FALSE;
}

<commit_msg>INTEGRATION: CWS calcwarnings (1.12.110); FILE MERGED 2006/12/06 13:34:19 nn 1.12.110.2: #i69284# warning-free: core, unxlngi6 2006/11/28 13:24:44 nn 1.12.110.1: #i69284# warning-free: core, wntmsci10<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: collect.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: vg $ $Date: 2007-02-27 12:13:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"

#include <string.h>

#ifndef _STREAM_HXX //autogen
#include <tools/stream.hxx>
#endif
#ifndef _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX
#include <unotools/transliterationwrapper.hxx>
#endif

#include "rechead.hxx"
#include "collect.hxx"
#include "document.hxx"         // fuer TypedStrData Konstruktor

// -----------------------------------------------------------------------

DataObject::~DataObject()
{
}

//------------------------------------------------------------------------
// Collection
//------------------------------------------------------------------------

void lcl_DeleteDataObjects( DataObject** p, USHORT nCount )
{
    if ( p )
    {
        for (USHORT i = 0; i < nCount; i++) delete p[i];
        delete[] p;
        p = NULL;
    }
}

Collection::Collection(USHORT nLim, USHORT nDel) :
    nCount ( 0 ),
    nLimit ( nLim ),
    nDelta ( nDel ),
    pItems ( NULL )
{
    if (nDelta > MAXDELTA)
        nDelta = MAXDELTA;
    else if (nDelta == 0)
        nDelta = 1;
    if (nLimit > MAXCOLLECTIONSIZE)
        nLimit = MAXCOLLECTIONSIZE;
    else if (nLimit < nDelta)
        nLimit = nDelta;
    pItems = new DataObject*[nLimit];
}

Collection::Collection(const Collection& rCollection)
    :   DataObject(),
        nCount ( 0 ),
        nLimit ( 0 ),
        nDelta ( 0 ),
        pItems ( NULL )
{
    *this = rCollection;
}

//------------------------------------------------------------------------

Collection::~Collection()
{
    lcl_DeleteDataObjects( pItems, nCount );
}

//------------------------------------------------------------------------

void Collection::AtFree(USHORT nIndex)
{
    if ((pItems) && (nIndex < nCount))
    {
        delete pItems[nIndex];
        --nCount;               // before memmove
        memmove ( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(DataObject*));
        pItems[nCount] = NULL;
    }
}

//------------------------------------------------------------------------

void Collection::Free(DataObject* pDataObject)
{
    AtFree(IndexOf(pDataObject));
}

//------------------------------------------------------------------------

void Collection::FreeAll()
{
    lcl_DeleteDataObjects( pItems, nCount );
    nCount = 0;
    pItems = new DataObject*[nLimit];
}

//------------------------------------------------------------------------

BOOL Collection::AtInsert(USHORT nIndex, DataObject* pDataObject)
{
    if ((nCount < MAXCOLLECTIONSIZE) && (nIndex <= nCount) && pItems)
    {
        if (nCount == nLimit)
        {
            DataObject** pNewItems = new DataObject*[nLimit + nDelta];
            if (!pNewItems)
                return FALSE;
            nLimit = sal::static_int_cast<USHORT>( nLimit + nDelta );
            memmove(pNewItems, pItems, nCount * sizeof(DataObject*));
            delete[] pItems;
            pItems = pNewItems;
        }
        if (nCount > nIndex)
            memmove(&pItems[nIndex + 1], &pItems[nIndex], (nCount - nIndex) * sizeof(DataObject*));
        pItems[nIndex] = pDataObject;
        nCount++;
        return TRUE;
    }
    return FALSE;
}

//------------------------------------------------------------------------

BOOL Collection::Insert(DataObject* pDataObject)
{
    return AtInsert(nCount, pDataObject);
}

//------------------------------------------------------------------------

DataObject* Collection::At(USHORT nIndex) const
{
    if (nIndex < nCount)
        return pItems[nIndex];
    else
        return NULL;
}

//------------------------------------------------------------------------

USHORT Collection::IndexOf(DataObject* pDataObject) const
{
    USHORT nIndex = 0xffff;
    for (USHORT i = 0; ((i < nCount) && (nIndex == 0xffff)); i++)
    {
        if (pItems[i] == pDataObject) nIndex = i;
    }
    return nIndex;
}

//------------------------------------------------------------------------

Collection& Collection::operator=( const Collection& r )
{
    lcl_DeleteDataObjects( pItems, nCount );

    nCount = r.nCount;
    nLimit = r.nLimit;
    nDelta = r.nDelta;
    pItems = new DataObject*[nLimit];
    for ( USHORT i=0; i<nCount; i++ )
        pItems[i] = r.pItems[i]->Clone();

    return *this;
}

//------------------------------------------------------------------------

DataObject* Collection::Clone() const
{
    return new Collection(*this);
}

//------------------------------------------------------------------------
// SortedCollection
//------------------------------------------------------------------------

SortedCollection::SortedCollection(USHORT nLim, USHORT nDel, BOOL bDup) :
    Collection (nLim, nDel),
    bDuplicates ( bDup)
{
}

//------------------------------------------------------------------------

USHORT SortedCollection::IndexOf(DataObject* pDataObject) const
{
    USHORT nIndex;
    if (Search(pDataObject, nIndex))
        return nIndex;
    else
        return 0xffff;
}

//------------------------------------------------------------------------

BOOL SortedCollection::Search(DataObject* pDataObject, USHORT& rIndex) const
{
    rIndex = nCount;
    BOOL bFound = FALSE;
    short nLo = 0;
    short nHi = nCount - 1;
    short nIndex;
    short nCompare;
    while (nLo <= nHi)
    {
        nIndex = (nLo + nHi) / 2;
        nCompare = Compare(pItems[nIndex], pDataObject);
        if (nCompare < 0)
            nLo = nIndex + 1;
        else
        {
            nHi = nIndex - 1;
            if (nCompare == 0)
            {
                bFound = TRUE;
                nLo = nIndex;
            }
        }
    }
    rIndex = nLo;
    return bFound;
}

//------------------------------------------------------------------------

BOOL SortedCollection::Insert(DataObject* pDataObject)
{
    USHORT nIndex;
    BOOL bFound = Search(pDataObject, nIndex);
    if (bFound)
    {
        if (bDuplicates)
            return AtInsert(nIndex, pDataObject);
        else
            return FALSE;
    }
    else
        return AtInsert(nIndex, pDataObject);
}

//------------------------------------------------------------------------

BOOL SortedCollection::InsertPos(DataObject* pDataObject, USHORT& nIndex)
{
    BOOL bFound = Search(pDataObject, nIndex);
    if (bFound)
    {
        if (bDuplicates)
            return AtInsert(nIndex, pDataObject);
        else
            return FALSE;
    }
    else
        return AtInsert(nIndex, pDataObject);
}

//------------------------------------------------------------------------

BOOL SortedCollection::operator==(const SortedCollection& rCmp) const
{
    if ( nCount != rCmp.nCount )
        return FALSE;
    for (USHORT i=0; i<nCount; i++)
        if ( !IsEqual(pItems[i],rCmp.pItems[i]) )
            return FALSE;
    return TRUE;
}

//------------------------------------------------------------------------

//  IsEqual - komplette Inhalte vergleichen

BOOL SortedCollection::IsEqual(DataObject* pKey1, DataObject* pKey2) const
{
    return ( Compare(pKey1, pKey2) == 0 );      // Default: nur Index vergleichen
}

//------------------------------------------------------------------------

DataObject* StrData::Clone() const
{
    return new StrData(*this);
}

//------------------------------------------------------------------------

short StrCollection::Compare(DataObject* pKey1, DataObject* pKey2) const
{
    StringCompare eComp = ((StrData*)pKey1)->aStr.CompareTo(((StrData*)pKey2)->aStr);
    if (eComp == COMPARE_EQUAL)
        return 0;
    else if (eComp == COMPARE_LESS)
        return -1;
    else
        return 1;
}

//------------------------------------------------------------------------

DataObject* StrCollection::Clone() const
{
    return new StrCollection(*this);
}

//------------------------------------------------------------------------

void StrCollection::Load( SvStream& rStream )
{
    ScReadHeader aHdr( rStream );
    lcl_DeleteDataObjects( pItems, nCount );
    BOOL bDups;
    rStream >> bDups;
    SetDups( bDups );
    rStream >> nCount >> nLimit >> nDelta;
    pItems = new DataObject*[nLimit];
    String aStr;
    rtl_TextEncoding eSet = rStream.GetStreamCharSet();
    for ( USHORT i=0; i<nCount; i++ )
    {
        rStream.ReadByteString( aStr, eSet );
        pItems[i] = new StrData( aStr );
    }
}

void StrCollection::Store( SvStream& rStream ) const
{
    ScWriteHeader aHdr( rStream );
    BOOL bDups = IsDups();
    rStream << bDups << nCount << nLimit << nDelta;
    rtl_TextEncoding eSet = rStream.GetStreamCharSet();
    for ( USHORT i=0; i<nCount; i++ )
    {
        rStream.WriteByteString( ((StrData*)pItems[i])->GetString(), eSet );
    }
}

//------------------------------------------------------------------------
// TypedStrCollection
//------------------------------------------------------------------------

TypedStrData::TypedStrData( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
                                BOOL bAllStrings )
{
    if ( pDoc->HasValueData( nCol, nRow, nTab ) )
    {
        pDoc->GetValue( nCol, nRow, nTab, nValue );
        if (bAllStrings)
            pDoc->GetString( nCol, nRow, nTab, aStrValue );
        nStrType = 0;
    }
    else
    {
        pDoc->GetString( nCol, nRow, nTab, aStrValue );
        nValue = 0.0;
        nStrType = 1;       //! Typ uebergeben ?
    }
}

DataObject* TypedStrData::Clone() const
{
    return new TypedStrData(*this);
}

DataObject* TypedStrCollection::Clone() const
{
    return new TypedStrCollection(*this);
}

short TypedStrCollection::Compare( DataObject* pKey1, DataObject* pKey2 ) const
{
    short nResult = 0;

    if ( pKey1 && pKey2 )
    {
        TypedStrData& rData1 = (TypedStrData&)*pKey1;
        TypedStrData& rData2 = (TypedStrData&)*pKey2;

        if ( rData1.nStrType > rData2.nStrType )
            nResult = 1;
        else if ( rData1.nStrType < rData2.nStrType )
            nResult = -1;
        else if ( !rData1.nStrType /* && !rData2.nStrType */ )
        {
            //--------------------
            // Zahlen vergleichen:
            //--------------------
            if ( rData1.nValue == rData2.nValue )
                nResult = 0;
            else if ( rData1.nValue < rData2.nValue )
                nResult = -1;
            else
                nResult = 1;
        }
        else /* if ( rData1.nStrType && rData2.nStrType ) */
        {
            //---------------------
            // Strings vergleichen:
            //---------------------
            if ( bCaseSensitive )
                nResult = (short) ScGlobal::pCaseTransliteration->compareString(
                    rData1.aStrValue, rData2.aStrValue );
            else
                nResult = (short) ScGlobal::pTransliteration->compareString(
                    rData1.aStrValue, rData2.aStrValue );
        }
    }

    return nResult;
}

BOOL TypedStrCollection::FindText( const String& rStart, String& rResult,
                                    USHORT& rPos, BOOL bBack ) const
{
    //  Die Collection ist nach String-Vergleichen sortiert, darum muss hier
    //  alles durchsucht werden

    BOOL bFound = FALSE;

    String aOldResult;
    if ( rPos != SCPOS_INVALID && rPos < nCount )
    {
        TypedStrData* pData = (TypedStrData*) pItems[rPos];
        if (pData->nStrType)
            aOldResult = pData->aStrValue;
    }

    if ( bBack )                                    // rueckwaerts
    {
        USHORT nStartPos = nCount;
        if ( rPos != SCPOS_INVALID )
            nStartPos = rPos;                       // weitersuchen...

        for ( USHORT i=nStartPos; i>0; )
        {
            --i;
            TypedStrData* pData = (TypedStrData*) pItems[i];
            if (pData->nStrType)
            {
                if ( ScGlobal::pTransliteration->isMatch( rStart, pData->aStrValue ) )
                {
                    //  If the collection is case sensitive, it may contain several entries
                    //  that are equal when compared case-insensitive. They are skipped here.
                    if ( !bCaseSensitive || !aOldResult.Len() ||
                            !ScGlobal::pTransliteration->isEqual(
                            pData->aStrValue, aOldResult ) )
                    {
                        rResult = pData->aStrValue;
                        rPos = i;
                        bFound = TRUE;
                        break;
                    }
                }
            }
        }
    }
    else                                            // vorwaerts
    {
        USHORT nStartPos = 0;
        if ( rPos != SCPOS_INVALID )
            nStartPos = rPos + 1;                   // weitersuchen...

        for ( USHORT i=nStartPos; i<nCount; i++ )
        {
            TypedStrData* pData = (TypedStrData*) pItems[i];
            if (pData->nStrType)
            {
                if ( ScGlobal::pTransliteration->isMatch( rStart, pData->aStrValue ) )
                {
                    //  If the collection is case sensitive, it may contain several entries
                    //  that are equal when compared case-insensitive. They are skipped here.
                    if ( !bCaseSensitive || !aOldResult.Len() ||
                            !ScGlobal::pTransliteration->isEqual(
                            pData->aStrValue, aOldResult ) )
                    {
                        rResult = pData->aStrValue;
                        rPos = i;
                        bFound = TRUE;
                        break;
                    }
                }
            }
        }
    }

    return bFound;
}

        // Gross-/Kleinschreibung anpassen

BOOL TypedStrCollection::GetExactMatch( String& rString ) const
{
    for (USHORT i=0; i<nCount; i++)
    {
        TypedStrData* pData = (TypedStrData*) pItems[i];
        if ( pData->nStrType && ScGlobal::pTransliteration->isEqual(
                pData->aStrValue, rString ) )
        {
            rString = pData->aStrValue;                         // String anpassen
            return TRUE;
        }
    }

    return FALSE;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: xlroot.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2003-10-21 08:49:35 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

// ============================================================================

#ifndef SC_XLROOT_HXX
#define SC_XLROOT_HXX

#ifndef SC_SCGLOB_HXX
#include "global.hxx"
#endif

#ifndef SC_XLTOOLS_HXX
#include "xltools.hxx"
#endif

// Global data ================================================================

class ScEditEngineDefaulter;
class ScHeaderEditEngine;
class EditEngine;
class XclTracer;

struct RootData;//!

/** Stores global buffers and data needed elsewhere in the Excel filters. */
struct XclRootData
{
    typedef ::std::auto_ptr< ScEditEngineDefaulter >    ScEditEngineDefaulterPtr;
    typedef ::std::auto_ptr< ScHeaderEditEngine >       ScHeaderEditEnginePtr;
    typedef ::std::auto_ptr< EditEngine >               EditEnginePtr;
    typedef ::std::auto_ptr< XclTracer >                XclTracerPtr;

    XclBiff                     meBiff;         /// Current BIFF version.
    ScDocument&                 mrDoc;          /// The source or destination document.
    String                      maDocUrl;       /// Document URL of imported/exported file.
    String                      maBasePath;     /// Base path of imported/exported file (path of maDocUrl).
    CharSet                     meCharSet;      /// Character set to import/export byte strings.
    LanguageType                meSysLang;      /// System language.
    LanguageType                meDocLang;      /// Document language (import: from file, export: from system).
    LanguageType                meUILang;       /// UI language (import: from file, export: from system).
    ScAddress                   maScMaxPos;     /// Highest Calc cell position.
    ScAddress                   maXclMaxPos;    /// Highest Excel cell position.
    long                        mnCharWidth;    /// Width of '0' in default font (twips).
    sal_uInt16                  mnScTab;        /// Current Calc sheet index.
    bool                        mbTruncated;    /// Flag for the table truncated warning box.

    ScEditEngineDefaulterPtr    mpEditEngine;   /// Edit engine for rich strings etc.
    ScHeaderEditEnginePtr       mpHFEditEngine; /// Edit engine for header/footer.
    EditEnginePtr               mpDrawEditEng;  /// Edit engine for text boxes.

    XclTracerPtr                mpTracer;       /// Filter tracer.

    ::std::auto_ptr< RootData > mpRDP;//!

#ifdef DBG_UTIL
    sal_Int32                   mnObjCnt;       /// Object counter for mem leak tests.
#endif

    explicit                    XclRootData(
                                    XclBiff eBiff,
                                    ScDocument& rDocument,
                                    const String& rDocUrl,
                                    CharSet eCharSet );
    virtual                     ~XclRootData();
};

// ----------------------------------------------------------------------------

class SfxObjectShell;
class ScModelObj;
class SfxPrinter;
class SvNumberFormatter;
class ScDocumentPool;
class ScStyleSheetPool;
class ScRangeName;
class SvStorage;
struct XclFontData;

/** Access to global data for a filter object (imported or exported document) from other classes. */
class XclRoot
{
private:
    mutable XclRootData&        mrData;     /// Reference to the global data struct.

public:
                                XclRoot( const XclRoot& rRoot );
    virtual                     ~XclRoot();

    XclRoot&                    operator=( const XclRoot& rRoot );

    RootData*                   mpRD;//!

    /** Returns this root instance - for code readability in derived classes. */
    inline const XclRoot&       GetRoot() const { return *this; }
    /** Returns the current BIFF version of the importer/exporter. */
    inline XclBiff              GetBiff() const { return mrData.meBiff; }
    /** Returns the system language, i.e. for number formats. */
    inline LanguageType         GetSysLanguage() const { return mrData.meSysLang; }
    /** Returns the document language. */
    inline LanguageType         GetDocLanguage() const { return mrData.meDocLang; }
    /** Returns the UI language. */
    inline LanguageType         GetUILanguage() const { return mrData.meUILang; }
    /** Returns the current Calc sheet index. */
    inline sal_uInt16           GetScTab() const { return mrData.mnScTab; }
    /** Returns whether the "some cells have been cut" warning box should show. */
    inline bool                 IsTruncated() const { return mrData.mbTruncated; }

    /** Returns the document URL of the imported/exported file. */
    inline const String&        GetDocUrl() const { return mrData.maDocUrl; }
    /** Returns the base path of the imported/exported file. */
    inline const String&        GetBasePath() const { return mrData.maBasePath; }
    /** Returns the character set to import/export byte strings. */
    inline CharSet              GetCharSet() const { return mrData.meCharSet; }
    /** Returns the width of the '0' character (default font) for the current printer (twips). */
    inline long                 GetCharWidth() const { return mrData.mnCharWidth; }

    /** Returns the destination document (import) or source document (export). */
    inline ScDocument&          GetDoc() const { return mrData.mrDoc; }
    /** Returns pointer to the destination document (import) or source document (export). */
    inline ScDocument*          GetDocPtr() const { return &mrData.mrDoc; }
    /** Returns the object shell of the Calc document. May be NULL (i.e. import from clipboard). */
    SfxObjectShell*             GetDocShell() const;
    /** Returns the object model of the Calc document. */
    ScModelObj*                 GetDocModelObj() const;
    /** Returns pointer to the printer of the Calc document. */
    SfxPrinter*                 GetPrinter() const;
    /** Returns the number formatter of the Calc document. */
    SvNumberFormatter&          GetFormatter() const;
    /** Returns the style sheet pool of the Calc document. */
    ScStyleSheetPool&           GetStyleSheetPool() const;
    /** Returns the defined names container of the Calc document. */
    ScRangeName&                GetNamedRanges() const;

    /** Returns the OLE2 root storage of the imported/exported file.
        @return  Pointer to root storage or 0, if the file is a simple stream. */
    SvStorage*                  GetRootStorage() const;

    /** Returns the edit engine for import/export of rich strings etc. */
    ScEditEngineDefaulter&      GetEditEngine() const;
    /** Returns the edit engine for import/export of headers/footers. */
    ScHeaderEditEngine&         GetHFEditEngine() const;
    /** Returns the edit engine for import/export of drawing text boxes. */
    EditEngine&                 GetDrawEditEngine() const;

    /** Returns the filter tracer. */
    XclTracer&                  GetTracer() const;

    /** Returns the highest possible cell address in a Calc document. */
    inline const ScAddress&     GetScMaxPos() const { return mrData.maScMaxPos; }
    /** Returns the highest possible cell address in an Excel document (using current BIFF version). */
    inline const ScAddress&     GetXclMaxPos() const { return mrData.maXclMaxPos; }

protected:
    explicit                    XclRoot( XclRootData& rRootData );

    /** Sets the BIFF version. */
    void                        SetBiff( XclBiff eBiff );
    /** Sets the document language. */
    inline void                 SetDocLanguage( LanguageType eLang ) { mrData.meDocLang = eLang; }
    /** Sets the UI language, i.e. if it has been read from a file. */
    inline void                 SetUILanguage( LanguageType eLang ) { mrData.meUILang = eLang; }
    /** Sets the character set to import/export byte strings. */
    inline void                 SetCharSet( CharSet eCharSet ) { mrData.meCharSet = eCharSet; }
    /** Sets the width of the '0' character (default font) for the current printer (twips).
        @param rFontData  The font used for the '0' character. */
    void                        SetCharWidth( const XclFontData& rFontData );
    /** Increases the current Calc sheet index by 1. */
    inline void                 IncScTab() { ++mrData.mnScTab; }
    /** Sets the maximum possible cell address according to the current BIFF version. */
    void                        SetMaxPos();

    /** Checks if the passed cell address is valid.
        @descr  Sets the internal flag that produces a warning box, if the cell is
        outside the passed maximum position.
        @param rPos  The cell address to check.
        @param rMaxPos  Highest valid cell address.
        @return  true = cell address is valid. */
    bool                        CheckCellAddress( const ScAddress& rPos, const ScAddress rMaxPos ) const;
    /** Checks and eventually crops the cell range to passed dimensions.
        @descr  Sets the internal flag that produces a warning box, if the cell range
        contains invalid cells. If the range is partly valid, this function sets
        the warning flag, corrects the range and returns true.
        @param rRange  (In/out) The cell range to check.
        @param rMaxPos  Highest valid cell address.
        @return  true = rRange contains a valid cell range (original or cropped). */
    bool                        CheckCellRange( ScRange& rRange, const ScAddress rMaxPos ) const;
    /** Checks and eventually crops the cell ranges to passed dimensions.
        @descr  Sets the internal flag that produces a warning box, if at least one
        cell range contains invalid cells. If the range is partly valid, this function
        sets the warning flag and corrects the range. Cell ranges which do not fit
        full or partly will be removed from the list.
        @param rRangeList  (In/out) The cell range list to check.
        @param rMaxPos  Highest valid cell address. */
    void                        CheckCellRangeList( ScRangeList& rRanges, const ScAddress& rMaxPos ) const;
};

// ============================================================================

#endif

<commit_msg>INTEGRATION: CWS calc17 (1.7.4); FILE MERGED 2003/10/27 11:47:39 dr 1.7.4.2: RESYNC: (1.7-1.8); FILE MERGED 2003/09/09 09:59:22 jmarmion 1.7.4.1: #112154# add selected trace features to excel import.<commit_after>/*************************************************************************
 *
 *  $RCSfile: xlroot.hxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2003-11-05 13:43:20 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

// ============================================================================

#ifndef SC_XLROOT_HXX
#define SC_XLROOT_HXX

#ifndef SC_SCGLOB_HXX
#include "global.hxx"
#endif

#ifndef SC_XLTOOLS_HXX
#include "xltools.hxx"
#endif

// Global data ================================================================

class ScEditEngineDefaulter;
class ScHeaderEditEngine;
class EditEngine;
class XclTracer;

struct RootData;//!

/** Stores global buffers and data needed elsewhere in the Excel filters. */
struct XclRootData
{
    typedef ::std::auto_ptr< ScEditEngineDefaulter >    ScEditEngineDefaulterPtr;
    typedef ::std::auto_ptr< ScHeaderEditEngine >       ScHeaderEditEnginePtr;
    typedef ::std::auto_ptr< EditEngine >               EditEnginePtr;
    typedef ::std::auto_ptr< XclTracer >                XclTracerPtr;

    XclBiff                     meBiff;         /// Current BIFF version.
    ScDocument&                 mrDoc;          /// The source or destination document.
    String                      maDocUrl;       /// Document URL of imported/exported file.
    String                      maBasePath;     /// Base path of imported/exported file (path of maDocUrl).
    CharSet                     meCharSet;      /// Character set to import/export byte strings.
    LanguageType                meSysLang;      /// System language.
    LanguageType                meDocLang;      /// Document language (import: from file, export: from system).
    LanguageType                meUILang;       /// UI language (import: from file, export: from system).
    ScAddress                   maScMaxPos;     /// Highest Calc cell position.
    ScAddress                   maXclMaxPos;    /// Highest Excel cell position.
    long                        mnCharWidth;    /// Width of '0' in default font (twips).
    sal_uInt16                  mnScTab;        /// Current Calc sheet index.
    bool                        mbTruncated;    /// Flag for the table truncated warning box.

    ScEditEngineDefaulterPtr    mpEditEngine;   /// Edit engine for rich strings etc.
    ScHeaderEditEnginePtr       mpHFEditEngine; /// Edit engine for header/footer.
    EditEnginePtr               mpDrawEditEng;  /// Edit engine for text boxes.

    XclTracerPtr                mpTracer;       /// Filter tracer.

    ::std::auto_ptr< RootData > mpRDP;//!

#ifdef DBG_UTIL
    sal_Int32                   mnObjCnt;       /// Object counter for mem leak tests.
#endif

    explicit                    XclRootData(
                                    XclBiff eBiff,
                                    ScDocument& rDocument,
                                    const String& rDocUrl,
                                    CharSet eCharSet );
    virtual                     ~XclRootData();
};

// ----------------------------------------------------------------------------

class SfxObjectShell;
class ScModelObj;
class SfxPrinter;
class SvNumberFormatter;
class ScDocumentPool;
class ScStyleSheetPool;
class ScRangeName;
class SvStorage;
struct XclFontData;

/** Access to global data for a filter object (imported or exported document) from other classes. */
class XclRoot
{
private:
    mutable XclRootData&        mrData;     /// Reference to the global data struct.

public:
                                XclRoot( const XclRoot& rRoot );
    virtual                     ~XclRoot();

    XclRoot&                    operator=( const XclRoot& rRoot );

    RootData*                   mpRD;//!

    /** Returns this root instance - for code readability in derived classes. */
    inline const XclRoot&       GetRoot() const { return *this; }
    /** Returns the current BIFF version of the importer/exporter. */
    inline XclBiff              GetBiff() const { return mrData.meBiff; }
    /** Returns the system language, i.e. for number formats. */
    inline LanguageType         GetSysLanguage() const { return mrData.meSysLang; }
    /** Returns the document language. */
    inline LanguageType         GetDocLanguage() const { return mrData.meDocLang; }
    /** Returns the UI language. */
    inline LanguageType         GetUILanguage() const { return mrData.meUILang; }
    /** Returns the current Calc sheet index. */
    inline sal_uInt16           GetScTab() const { return mrData.mnScTab; }
    /** Returns whether the "some cells have been cut" warning box should show. */
    inline bool                 IsTruncated() const { return mrData.mbTruncated; }

    /** Returns the document URL of the imported/exported file. */
    inline const String&        GetDocUrl() const { return mrData.maDocUrl; }
    /** Returns the base path of the imported/exported file. */
    inline const String&        GetBasePath() const { return mrData.maBasePath; }
    /** Returns the character set to import/export byte strings. */
    inline CharSet              GetCharSet() const { return mrData.meCharSet; }
    /** Returns the width of the '0' character (default font) for the current printer (twips). */
    inline long                 GetCharWidth() const { return mrData.mnCharWidth; }

    /** Returns the destination document (import) or source document (export). */
    inline ScDocument&          GetDoc() const { return mrData.mrDoc; }
    /** Returns pointer to the destination document (import) or source document (export). */
    inline ScDocument*          GetDocPtr() const { return &mrData.mrDoc; }
    /** Returns the object shell of the Calc document. May be NULL (i.e. import from clipboard). */
    SfxObjectShell*             GetDocShell() const;
    /** Returns the object model of the Calc document. */
    ScModelObj*                 GetDocModelObj() const;
    /** Returns pointer to the printer of the Calc document. */
    SfxPrinter*                 GetPrinter() const;
    /** Returns the number formatter of the Calc document. */
    SvNumberFormatter&          GetFormatter() const;
    /** Returns the style sheet pool of the Calc document. */
    ScStyleSheetPool&           GetStyleSheetPool() const;
    /** Returns the defined names container of the Calc document. */
    ScRangeName&                GetNamedRanges() const;

    /** Returns the OLE2 root storage of the imported/exported file.
        @return  Pointer to root storage or 0, if the file is a simple stream. */
    SvStorage*                  GetRootStorage() const;

    /** Returns the edit engine for import/export of rich strings etc. */
    ScEditEngineDefaulter&      GetEditEngine() const;
    /** Returns the edit engine for import/export of headers/footers. */
    ScHeaderEditEngine&         GetHFEditEngine() const;
    /** Returns the edit engine for import/export of drawing text boxes. */
    EditEngine&                 GetDrawEditEngine() const;

    /** Returns the filter tracer. */
    XclTracer&                  GetTracer() const;

    /** Returns the highest possible cell address in a Calc document. */
    inline const ScAddress&     GetScMaxPos() const { return mrData.maScMaxPos; }
    /** Returns the highest possible cell address in an Excel document (using current BIFF version). */
    inline const ScAddress&     GetXclMaxPos() const { return mrData.maXclMaxPos; }

protected:
    explicit                    XclRoot( XclRootData& rRootData );

    /** Sets the BIFF version. */
    void                        SetBiff( XclBiff eBiff );
    /** Sets the document language. */
    inline void                 SetDocLanguage( LanguageType eLang ) { mrData.meDocLang = eLang; }
    /** Sets the UI language, i.e. if it has been read from a file. */
    inline void                 SetUILanguage( LanguageType eLang ) { mrData.meUILang = eLang; }
    /** Sets the character set to import/export byte strings. */
    inline void                 SetCharSet( CharSet eCharSet ) { mrData.meCharSet = eCharSet; }
    /** Sets the width of the '0' character (default font) for the current printer (twips).
        @param rFontData  The font used for the '0' character. */
    void                        SetCharWidth( const XclFontData& rFontData );
    /** Increases the current Calc sheet index by 1. */
    inline void                 IncScTab() { ++mrData.mnScTab; }
    /** Sets the maximum possible cell address according to the current BIFF version. */
    void                        SetMaxPos();

    /** Checks if the passed cell address is valid.
        @descr  Sets the internal flag that produces a warning box, if the cell is
        outside the passed maximum position.
        @param rPos  The cell address to check.
        @param rMaxPos  Highest valid cell address.
        @return  true = cell address is valid. */
    bool                        CheckCellAddress( const ScAddress& rPos, const ScAddress& rMaxPos ) const;
    /** Checks and eventually crops the cell range to passed dimensions.
        @descr  Sets the internal flag that produces a warning box, if the cell range
        contains invalid cells. If the range is partly valid, this function sets
        the warning flag, corrects the range and returns true.
        @param rRange  (In/out) The cell range to check.
        @param rMaxPos  Highest valid cell address.
        @return  true = rRange contains a valid cell range (original or cropped). */
    bool                        CheckCellRange( ScRange& rRange, const ScAddress& rMaxPos ) const;
    /** Checks and eventually crops the cell ranges to passed dimensions.
        @descr  Sets the internal flag that produces a warning box, if at least one
        cell range contains invalid cells. If the range is partly valid, this function
        sets the warning flag and corrects the range. Cell ranges which do not fit
        full or partly will be removed from the list.
        @param rRangeList  (In/out) The cell range list to check.
        @param rMaxPos  Highest valid cell address. */
    void                        CheckCellRangeList( ScRangeList& rRanges, const ScAddress& rMaxPos ) const;
};

// ============================================================================

#endif

<|endoftext|>


<commit_before>// $Id: LineBasedFile_test.C,v 1.5 2000/10/15 22:35:30 amoll Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/FORMAT/lineBasedFile.h>
///////////////////////////

START_TEST(class_name, "$Id: LineBasedFile_test.C,v 1.5 2000/10/15 22:35:30 amoll Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;

CHECK(BALL_CREATE(LineBasedFile))
  //BAUSTELLE
RESULT

LineBasedFile* fl;

CHECK(LineBasedFile() throw())
	fl = new LineBasedFile;
	TEST_NOT_EQUAL(fl, 0)
RESULT

CHECK(~LineBasedFile() throw())
	delete fl;
RESULT

CHECK(LineBasedFile(const String& filename, File::OpenMode open_mode = File::IN)
			throw(Exception::FileNotFound))
	LineBasedFile f1("data/LineBasedFile_test.txt");
	TEST_EQUAL(f1.getLineNumber(), 0)
	TEST_EQUAL(f1.getLine(), "")
	f1.readLine();
	TEST_EQUAL(f1.getLineNumber(), 1)
	TEST_EQUAL(f1.getLine(), "line1")

	TEST_EXCEPTION(Exception::FileNotFound, LineBasedFile f2("XXXXXXXX.txt"))
RESULT

LineBasedFile fx;

CHECK(LineBasedFile(const LineBasedFile& f) throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	f1.readLine();
	LineBasedFile f2(f1);

	TEST_EQUAL(f2.getLineNumber(), 1)
	TEST_EQUAL(f2.getLine(), "line1")
RESULT

CHECK(LineBasedFile& operator = (const LineBasedFile& file) throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	f1.readLine();
	LineBasedFile f2(f1);
	TEST_EQUAL(f2.getLineNumber(), 1)
	TEST_EQUAL(f2.getLine(), "line1")
RESULT

CHECK(clear() throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	f1.readLine();
	f1.clear();
	TEST_EQUAL(f1.getLineNumber(), 0)
	TEST_EQUAL(f1.getLine(), "")

	fx.clear();
RESULT

CHECK(getLineNumber() const  throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	TEST_EQUAL(f1.getLineNumber(), 0)
	f1.readLine();
	TEST_EQUAL(f1.getLineNumber(), 1)

	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

LineBasedFile f1("data/LineBasedFile_test.txt");

CHECK(getLine() const  throw())
	TEST_EQUAL(f1.getLine(), "")
	f1.readLine();
	TEST_EQUAL(f1.getLine(), "line1")

	TEST_EQUAL(fx.getLine(), "")
RESULT

CHECK(getField(Position pos = 0, const String& quotes = "",
			const String& delimiters = String::CHARACTER_CLASS__WHITESPACE)
			const  throw(Exception::IndexUnderflow))

	TEST_EQUAL(f1.getField(), "line1")
	TEST_EQUAL(f1.getField(1), "")
	TEST_EXCEPTION(Exception::IndexUnderflow, f1.getField(-99))
	f1.readLine();
	TEST_EQUAL(f1.getField(), "/0/")
	TEST_EQUAL(f1.getField(1), "/1/")
	TEST_EQUAL(f1.getField(2), "/2")
	TEST_EQUAL(f1.getField(0, "/"), "0")
	TEST_EQUAL(f1.getField(1, "/"), "1")
	TEST_EQUAL(f1.getField(2, "/"), "2 23")
	TEST_EQUAL(f1.getField(3, "/"), "")

	TEST_EQUAL(fx.getField(), "")
RESULT

CHECK(startsWith(const String& text) const  throw())
	TEST_EQUAL(f1.startsWith("/0/"), true)
	TEST_EQUAL(f1.startsWith("/0/ /1/ /2 2//3/"), true)
	TEST_EQUAL(f1.startsWith("/0/ /1/ /2 2//3/X"), false)

	TEST_EQUAL(fx.startsWith(""), true)
RESULT

CHECK(has(const String& text) const  throw())
	TEST_EQUAL(f1.has("/0/"), true)
	TEST_EQUAL(f1.has("/1/"), true)
	TEST_EQUAL(f1.has("/3/"), true)
	TEST_EQUAL(f1.has("X"), false)

	TEST_EQUAL(fx.has("X"), false)
	TEST_EQUAL(fx.has(""), true)
RESULT

CHECK(search(const String& text) throw())
	TEST_EQUAL(f1.search("line3"), true)
	TEST_EQUAL(f1.search("line4-"), true)
	TEST_EQUAL(f1.search("line4-"), false)

  f1.rewind();
	f1.skipLines(2);
	TEST_EQUAL(f1.getLine(), "line3-")
	f1.search("XXX", true);
	TEST_EQUAL(f1.getLine(), "line3-")

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.search("line4-"))
RESULT

CHECK(search(const String& text, const String& stop) throw())
  f1.rewind();
	TEST_EQUAL(f1.search("line3", "line4", true), true)
  f1.rewind();
	TEST_EQUAL(f1.search("line4", "line3", true), false)

  f1.rewind();
	f1.skipLines(2);
	TEST_EQUAL(f1.getLine(), "line3-")
	f1.search("XXX", "line4", true);
	TEST_EQUAL(f1.getLine(), "line3-")

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.search("line4", "line3"))
RESULT

CHECK(switchString(const std::vector<String>& data) const  throw())
  f1.rewind();
	f1.readLine();

	vector<String> vec;
	vec.push_back("line");
	vec.push_back("line1");
	vec.push_back("line2");
	vec.push_back("");

	TEST_EQUAL(f1.switchString(vec), 1)
	f1.readLine();
	TEST_EQUAL(f1.switchString(vec), -1)

	TEST_EQUAL(fx.switchString(vec), 3)
RESULT

CHECK(test(const char* file, int line, bool condition, const String& msg)
			const  throw(LineBasedFileError))
	f1.test(__FILE__, __LINE__, true, "test");
	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, f1.test(__FILE__, __LINE__, false, "test") )
	fx.test(__FILE__, __LINE__, true, "test");
RESULT

CHECK(readLine() throw(LineBasedFileError))
  f1.rewind();
	f1.readLine();

	TEST_EQUAL(f1.getLine(), "line1")

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.readLine())
	TEST_EQUAL(fx.getLine(), "")
RESULT

CHECK(skipLines(Size number = 1) throw(Exception::IndexUnderflow, LineBasedFileError))
  f1.rewind();
	TEST_EQUAL(f1.skipLines(2), true)
	TEST_EQUAL(f1.getLine(), "line3-")
	TEST_EQUAL(f1.getLineNumber(), 3)
	TEST_EQUAL(f1.skipLines(2), false)

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.skipLines(2))
	TEST_EQUAL(fx.getLine(), "")
	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

CHECK(rewind() throw(LineBasedFileError))
  f1.rewind();
	TEST_EQUAL(f1.getLine(), "")
	TEST_EQUAL(f1.getLineNumber(), 0)

  TEST_EXCEPTION(LineBasedFile::LineBasedFileError,fx.rewind())
	TEST_EQUAL(fx.getLine(), "")
	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

CHECK(goToLine(Position line_number) throw(LineBasedFileError))
  f1.rewind();
	f1.skipLines(4);
	TEST_EQUAL(f1.goToLine(3), true)
	TEST_EQUAL(f1.getLine(), "line3-" )

	TEST_EQUAL(f1.goToLine(5), true)
	TEST_EQUAL(f1.getLine(), "line5-" )

	TEST_EQUAL(f1.goToLine(6), false)
	TEST_EQUAL(f1.getLine(), "line5-" )

  TEST_EXCEPTION(LineBasedFile::LineBasedFileError,fx.goToLine(2))
	TEST_EQUAL(fx.getLine(), "")
	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<commit_msg>fixed test for cpy-constr.<commit_after>// $Id: LineBasedFile_test.C,v 1.6 2000/10/16 15:11:53 amoll Exp $
#include <BALL/CONCEPT/classTest.h>

///////////////////////////
#include <BALL/FORMAT/lineBasedFile.h>
///////////////////////////

START_TEST(class_name, "$Id: LineBasedFile_test.C,v 1.6 2000/10/16 15:11:53 amoll Exp $")

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////

using namespace BALL;

CHECK(BALL_CREATE(LineBasedFile))
  //BAUSTELLE
RESULT

LineBasedFile* fl;

CHECK(LineBasedFile() throw())
	fl = new LineBasedFile;
	TEST_NOT_EQUAL(fl, 0)
RESULT

CHECK(~LineBasedFile() throw())
	delete fl;
RESULT

CHECK(LineBasedFile(const String& filename, File::OpenMode open_mode = File::IN)
			throw(Exception::FileNotFound))
	LineBasedFile f1("data/LineBasedFile_test.txt");
	TEST_EQUAL(f1.getLineNumber(), 0)
	TEST_EQUAL(f1.getLine(), "")
	f1.readLine();
	TEST_EQUAL(f1.getLineNumber(), 1)
	TEST_EQUAL(f1.getLine(), "line1")

	TEST_EXCEPTION(Exception::FileNotFound, LineBasedFile f2("XXXXXXXX.txt"))
RESULT

LineBasedFile fx;

CHECK(LineBasedFile(const LineBasedFile& f) throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	f1.readLine();
	TEST_EQUAL(f1.getLine(), "line1")
	f1.close();

	LineBasedFile f2(f1);
	TEST_EQUAL(f2.getLineNumber(), 1)
	TEST_EQUAL(f2.getLine(), "line1")
	f2.readLine();
	TEST_EQUAL(f2.getLine(), "/0/ /1/ /2 2//3/")
RESULT

CHECK(LineBasedFile& operator = (const LineBasedFile& file) throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	f1.readLine();
	TEST_EQUAL(f1.getLine(), "line1")

	LineBasedFile f2;
	f2 = f1;/*
	TEST_EQUAL(f2.getLineNumber(), 1)
	TEST_EQUAL(f2.getLine(), "line1")*/
RESULT

CHECK(clear() throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	f1.readLine();
	f1.clear();
	TEST_EQUAL(f1.getLineNumber(), 0)
	TEST_EQUAL(f1.getLine(), "")

	fx.clear();
RESULT

CHECK(getLineNumber() const  throw())
	LineBasedFile f1("data/LineBasedFile_test.txt");
	TEST_EQUAL(f1.getLineNumber(), 0)
	f1.readLine();
	TEST_EQUAL(f1.getLineNumber(), 1)

	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

LineBasedFile f1("data/LineBasedFile_test.txt");

CHECK(getLine() const  throw())
	TEST_EQUAL(f1.getLine(), "")
	f1.readLine();
	TEST_EQUAL(f1.getLine(), "line1")

	TEST_EQUAL(fx.getLine(), "")
RESULT

CHECK(getField(Position pos = 0, const String& quotes = "",
			const String& delimiters = String::CHARACTER_CLASS__WHITESPACE)
			const  throw(Exception::IndexUnderflow))

	TEST_EQUAL(f1.getField(), "line1")
	TEST_EQUAL(f1.getField(1), "")
	TEST_EXCEPTION(Exception::IndexUnderflow, f1.getField(-99))
	f1.readLine();
	TEST_EQUAL(f1.getField(), "/0/")
	TEST_EQUAL(f1.getField(1), "/1/")
	TEST_EQUAL(f1.getField(2), "/2")
	TEST_EQUAL(f1.getField(0, "/"), "0")
	TEST_EQUAL(f1.getField(1, "/"), "1")
	TEST_EQUAL(f1.getField(2, "/"), "2 23")
	TEST_EQUAL(f1.getField(3, "/"), "")

	TEST_EQUAL(fx.getField(), "")
RESULT

CHECK(startsWith(const String& text) const  throw())
	TEST_EQUAL(f1.startsWith("/0/"), true)
	TEST_EQUAL(f1.startsWith("/0/ /1/ /2 2//3/"), true)
	TEST_EQUAL(f1.startsWith("/0/ /1/ /2 2//3/X"), false)

	TEST_EQUAL(fx.startsWith(""), true)
RESULT

CHECK(has(const String& text) const  throw())
	TEST_EQUAL(f1.has("/0/"), true)
	TEST_EQUAL(f1.has("/1/"), true)
	TEST_EQUAL(f1.has("/3/"), true)
	TEST_EQUAL(f1.has("X"), false)

	TEST_EQUAL(fx.has("X"), false)
	TEST_EQUAL(fx.has(""), true)
RESULT

CHECK(search(const String& text) throw())
	TEST_EQUAL(f1.search("line3"), true)
	TEST_EQUAL(f1.search("line4-"), true)
	TEST_EQUAL(f1.search("line4-"), false)

  f1.rewind();
	f1.skipLines(2);
	TEST_EQUAL(f1.getLine(), "line3-")
	f1.search("XXX", true);
	TEST_EQUAL(f1.getLine(), "line3-")

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.search("line4-"))
RESULT

CHECK(search(const String& text, const String& stop) throw())
  f1.rewind();
	TEST_EQUAL(f1.search("line3", "line4", true), true)
  f1.rewind();
	TEST_EQUAL(f1.search("line4", "line3", true), false)

  f1.rewind();
	f1.skipLines(2);
	TEST_EQUAL(f1.getLine(), "line3-")
	f1.search("XXX", "line4", true);
	TEST_EQUAL(f1.getLine(), "line3-")

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.search("line4", "line3"))
RESULT

CHECK(switchString(const std::vector<String>& data) const  throw())
  f1.rewind();
	f1.readLine();

	vector<String> vec;
	vec.push_back("line");
	vec.push_back("line1");
	vec.push_back("line2");
	vec.push_back("");

	TEST_EQUAL(f1.switchString(vec), 1)
	f1.readLine();
	TEST_EQUAL(f1.switchString(vec), -1)

	TEST_EQUAL(fx.switchString(vec), 3)
RESULT

CHECK(test(const char* file, int line, bool condition, const String& msg)
			const  throw(LineBasedFileError))
	f1.test(__FILE__, __LINE__, true, "test");
	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, f1.test(__FILE__, __LINE__, false, "test") )
	fx.test(__FILE__, __LINE__, true, "test");
RESULT

CHECK(readLine() throw(LineBasedFileError))
  f1.rewind();
	f1.readLine();

	TEST_EQUAL(f1.getLine(), "line1")

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.readLine())
	TEST_EQUAL(fx.getLine(), "")
RESULT

CHECK(skipLines(Size number = 1) throw(Exception::IndexUnderflow, LineBasedFileError))
  f1.rewind();
	TEST_EQUAL(f1.skipLines(2), true)
	TEST_EQUAL(f1.getLine(), "line3-")
	TEST_EQUAL(f1.getLineNumber(), 3)
	TEST_EQUAL(f1.skipLines(2), false)

	TEST_EXCEPTION(LineBasedFile::LineBasedFileError, fx.skipLines(2))
	TEST_EQUAL(fx.getLine(), "")
	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

CHECK(rewind() throw(LineBasedFileError))
  f1.rewind();
	TEST_EQUAL(f1.getLine(), "")
	TEST_EQUAL(f1.getLineNumber(), 0)

  TEST_EXCEPTION(LineBasedFile::LineBasedFileError,fx.rewind())
	TEST_EQUAL(fx.getLine(), "")
	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

CHECK(goToLine(Position line_number) throw(LineBasedFileError))
  f1.rewind();
	f1.skipLines(4);
	TEST_EQUAL(f1.goToLine(3), true)
	TEST_EQUAL(f1.getLine(), "line3-" )

	TEST_EQUAL(f1.goToLine(5), true)
	TEST_EQUAL(f1.getLine(), "line5-" )

	TEST_EQUAL(f1.goToLine(6), false)
	TEST_EQUAL(f1.getLine(), "line5-" )

  TEST_EXCEPTION(LineBasedFile::LineBasedFileError,fx.goToLine(2))
	TEST_EQUAL(fx.getLine(), "")
	TEST_EQUAL(fx.getLineNumber(), 0)
RESULT

/////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
END_TEST
<|endoftext|>