diff --git a/app/main.cpp b/app/main.cpp
index be938b4..3e70f67 100644
--- a/app/main.cpp
+++ b/app/main.cpp
@@ -47,15 +47,12 @@ int main( int argc, char *argv[] )
     KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
     KApplication app;
 
-    for ( int i = 0; i < args->count(); ++i ) {
-        Massif::MainWindow* window = new Massif::MainWindow;
+    Massif::MainWindow* window = new Massif::MainWindow;
+
+    for (int i = 0; i < args->count(); ++i) {
         window->openFile(args->url(i));
-        window->show();
-    }
-    if (!args->count()) {
-        // at least one window has to be shown...
-        Massif::MainWindow* window = new Massif::MainWindow;
-        window->show();
     }
+
+    window->show();
     return app.exec();
 }
diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp
index b33ff60..8853da4 100644
--- a/app/mainwindow.cpp
+++ b/app/mainwindow.cpp
@@ -2,6 +2,7 @@
    This file is part of Massif Visualizer
 
    Copyright 2010 Milian Wolff <mail@milianw.de>
+   Copyright 2013 Arnold Dumas <contact@arnolddumas.com>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -65,6 +66,7 @@
 #include <QInputDialog>
 #include <QPrinter>
 #include <QPrintDialog>
+#include <QTimer>
 
 #include <KDebug>
 #include <KMessageBox>
@@ -115,20 +117,11 @@ KConfigGroup allocatorConfig()
 //END Helper Functions
 
 MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f)
-    : KParts::MainWindow(parent, f), m_chart(new Chart(this)), m_header(new QLabel(this))
+    : KParts::MainWindow(parent, f)
     , m_toggleTotal(0)
-    , m_totalDiagram(0)
-    , m_totalCostModel(new TotalCostModel(m_chart))
     , m_toggleDetailed(0)
-    , m_detailedDiagram(0)
-    , m_detailedCostModel(new DetailedCostModel(m_chart))
-    , m_legend(new Legend(m_chart))
-    , m_dataTreeModel(new DataTreeModel(m_chart))
-    , m_dataTreeFilterModel(new FilteredDataTreeModel(m_dataTreeModel))
-    , m_data(0)
     , m_selectPeak(0)
     , m_recentFiles(0)
-    , m_changingSelections(false)
 #ifdef HAVE_KGRAPHVIEWER
     , m_graphViewerPart(0)
     , m_graphViewer(0)
@@ -145,42 +138,15 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f)
     , m_removeAllocator(0)
     , m_shortenTemplates(0)
     , m_parseWorker(new ParseWorker)
+    , m_isParseWorkerRunning(false)
 {
     ui.setupUi(this);
 
-    setWindowTitle(i18n("Massif Visualizer"));
+    updateWindowTitle();
 
-    // for axis labels to fit
-    m_chart->setGlobalLeadingRight(10);
-    m_chart->setGlobalLeadingLeft(10);
-    m_chart->setGlobalLeadingTop(20);
-    connect(m_chart, SIGNAL(customContextMenuRequested(QPoint)),
-            this, SLOT(chartContextMenuRequested(QPoint)));
-    m_chart->setContextMenuPolicy(Qt::CustomContextMenu);
-
-    m_legend->setPosition(Position(KDChartEnums::PositionFloating));
-    m_legend->setTitleText("");
-    m_legend->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
-    m_legend->setSortOrder(Qt::DescendingOrder);
-
-    m_chart->addLegend(m_legend);
-
-    //NOTE: this has to be set _after_ the legend was added to the chart...
-    TextAttributes att = m_legend->textAttributes();
-    att.setAutoShrink(true);
-    att.setFontSize( Measure(12) );
-    QFont font("monospace");
-    font.setStyleHint(QFont::TypeWriter);
-    att.setFont(font);
-    m_legend->setTextAttributes(att);
-    m_legend->setTextAlignment(Qt::AlignLeft);
-    m_legend->hide();
-
-    ui.plotterTab->layout()->addWidget(m_header);
-    ui.plotterTab->layout()->addWidget(m_chart);
+    connect(ui.filesTabWidget, SIGNAL(currentChanged(int)), this, SLOT(fileTabChanged(int)));
 
     //BEGIN KGraphViewer
-
     bool haveGraphViewer = false;
 
 #ifdef HAVE_KGRAPHVIEWER
@@ -189,7 +155,7 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f)
         m_graphViewerPart = factory->create<KParts::ReadOnlyPart>(this);
         if (m_graphViewerPart) {
             m_graphViewer = qobject_cast< KGraphViewer::KGraphViewerInterface* >(m_graphViewerPart);
-            ui.dotGraphTab->layout()->addWidget(m_graphViewerPart->widget());
+            //ui.dotGraphTab->layout()->addWidget(m_graphViewerPart->widget());
             connect(m_graphViewerPart, SIGNAL(graphLoaded()), this, SLOT(slotGraphLoaded()));
             haveGraphViewer = true;
         }
@@ -197,13 +163,6 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f)
 #endif
     //END KGraphViewer
 
-    connect(ui.filterDataTree, SIGNAL(textChanged(QString)),
-            m_dataTreeFilterModel, SLOT(setFilter(QString)));
-    ui.dataTreeView->setModel(m_dataTreeFilterModel);
-    connect(ui.dataTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
-            this, SLOT(treeSelectionChanged(QModelIndex,QModelIndex)));
-
-
     //BEGIN custom allocators
     tabifyDockWidget(ui.allocatorDock, ui.dataTreeDock);
     ui.allocatorView->setModel(m_allocatorModel);
@@ -238,20 +197,20 @@ MainWindow::MainWindow(QWidget* parent, Qt::WindowFlags f)
 
     if (haveGraphViewer) {
 #ifdef HAVE_KGRAPHVIEWER
-        connect(ui.tabWidget, SIGNAL(currentChanged(int)),
+        /*connect(ui.tabWidget, SIGNAL(currentChanged(int)),
                 this, SLOT(slotTabChanged(int)));
-        slotTabChanged(ui.tabWidget->currentIndex());
+        slotTabChanged(ui.tabWidget->currentIndex());*/
 #endif
     } else {
         // cleanup UI when we installed with kgraphviewer but it's not available at runtime
         KToolBar* callgraphToolbar = toolBar("callgraphToolBar");
         removeToolBar(callgraphToolbar);
         delete callgraphToolbar;
-        int i = ui.stackedWidget->addWidget(ui.plotterTab);
+        /*int i = ui.stackedWidget->addWidget(ui.plotterTab);
         ui.stackedWidget->setCurrentIndex(i);
         ui.stackedWidget->removeWidget(ui.displayPage);
         delete ui.displayPage;
-        ui.displayPage = ui.plotterTab;
+        ui.displayPage = ui.plotterTab;*/
     }
 
     // open page
@@ -277,7 +236,11 @@ MainWindow::~MainWindow()
     m_parseWorker->deleteLater();
     m_parseWorker->thread()->quit();
     m_parseWorker->thread()->wait();
-    closeFile();
+
+    while (ui.filesTabWidget->count()) {
+        closeCurrentFile();
+    }
+
     m_recentFiles->saveEntries(KGlobal::config()->group( QString() ));
 }
 
@@ -289,7 +252,7 @@ void MainWindow::setupActions()
     m_recentFiles = KStandardAction::openRecent(this, SLOT(openFile(KUrl)), actionCollection());
     m_recentFiles->loadEntries(KGlobal::config()->group( QString() ));
 
-    m_close = KStandardAction::close(this, SLOT(closeFile()), actionCollection());
+    m_close = KStandardAction::close(this, SLOT(closeCurrentFile()), actionCollection());
     m_close->setEnabled(false);
 
     m_print = KStandardAction::print(this, SLOT(showPrintPreviewDialog()), actionCollection());
@@ -421,7 +384,7 @@ void MainWindow::settingsChanged()
 
     Settings::self()->writeConfig();
 
-    if (m_data) {
+    if (currentFileData()) {
         updateHeader();
         updatePeaks();
     }
@@ -430,19 +393,18 @@ void MainWindow::settingsChanged()
 
 void MainWindow::openFile()
 {
-    QString file = KFileDialog::getOpenFileName(KUrl("kfiledialog:///massif-visualizer"),
+    QStringList files = KFileDialog::getOpenFileNames(KUrl("kfiledialog:///massif-visualizer"),
                                                 QString("application/x-valgrind-massif"),
                                                 this, i18n("Open Massif Output File"));
-    if (!file.isEmpty()) {
-        openFile(KUrl(file));
+    foreach (QString file, files) {
+        openFile(file, false);
     }
 }
 
 void MainWindow::reload()
 {
-    if (m_currentFile.isValid()) {
-        // copy to prevent madness
-        openFile(KUrl(m_currentFile));
+    if (currentFile().isValid()) {
+        openFile(currentFile(), true);
     }
 }
 
@@ -450,17 +412,36 @@ void MainWindow::stopParser()
 {
     m_parseWorker->stop();
     m_stopParser->setEnabled(false);
-    ui.stackedWidget->setCurrentWidget(ui.openPage);
+    m_isParseWorkerRunning = false;
+
+    if (ui.filesTabWidget->count()) {
+        ui.stackedWidget->setCurrentWidget(ui.displayPage);
+    } else {
+        ui.stackedWidget->setCurrentWidget(ui.openPage);
+    }
 }
 
-void MainWindow::openFile(const KUrl& file)
+void MainWindow::openFile(const KUrl& file, bool reload)
 {
     Q_ASSERT(file.isValid());
-    if (m_data) {
-        closeFile();
+
+    int fileTabIndex = m_openedFiles.indexOf(file);
+    if (fileTabIndex != -1) {
+        if (!reload) {
+            ui.filesTabWidget->setCurrentIndex(fileTabIndex);
+            return;
+        } else {
+            // TODO (arnold): insert new tab at the right position.
+            return;
+        }
     }
 
-    stopParser();
+    // Ensure that the previous file is full loaded
+    // instead of just stopping the parser.
+    if (m_isParseWorkerRunning) {
+        openFileLater(file, reload);
+        return;
+    }
 
     m_stopParser->setEnabled(true);
     ui.stackedWidget->setCurrentWidget(ui.loadingPage);
@@ -468,70 +449,112 @@ void MainWindow::openFile(const KUrl& file)
     ui.loadingMessage->setText(i18n("loading file <i>%1</i>...", file.pathOrUrl()));
 
     m_parseWorker->parse(file, m_allocatorModel->stringList());
+    m_isParseWorkerRunning = true;
 }
 
 void MainWindow::parserFinished(const KUrl& file, FileData* data)
 {
+    m_isParseWorkerRunning = false;
+
     // give the progress bar one last chance to update
     QApplication::processEvents();
 
-    m_data = data;
-    m_currentFile = file;
+    Q_ASSERT(data->peak());
 
-    Q_ASSERT(m_data->peak());
+    m_fileDataVector.append(data);
+    m_openedFiles.append(file);
+    m_recentFiles->addUrl(file);
+    m_changingSelectionsVector.append(false);
 
     m_close->setEnabled(true);
     m_print->setEnabled(true);
 
-    kDebug() << "loaded massif file:" << m_currentFile;
-    qDebug() << "description:" << m_data->description();
-    qDebug() << "command:" << m_data->cmd();
-    qDebug() << "time unit:" << m_data->timeUnit();
-    qDebug() << "snapshots:" << m_data->snapshots().size();
-    qDebug() << "peak: snapshot #" << m_data->peak()->number() << "after" << QString("%1%2").arg(m_data->peak()->time()).arg(m_data->timeUnit());
-    qDebug() << "peak cost:" << prettyCost(m_data->peak()->memHeap()) << " heap"
-                             << prettyCost(m_data->peak()->memHeapExtra()) << " heap extra"
-                             << prettyCost(m_data->peak()->memStacks()) << " stacks";
-
-    //BEGIN DotGraph
+    kDebug() << "loaded massif file:" << file;
+    qDebug() << "description:" << data->description();
+    qDebug() << "command:" << data->cmd();
+    qDebug() << "time unit:" << data->timeUnit();
+    qDebug() << "snapshots:" << data->snapshots().size();
+    qDebug() << "peak: snapshot #" << data->peak()->number() << "after" << QString("%1%2").arg(data->peak()->time()).arg(data->timeUnit());
+    qDebug() << "peak cost:" << prettyCost(data->peak()->memHeap()) << " heap"
+                             << prettyCost(data->peak()->memHeapExtra()) << " heap extra"
+                             << prettyCost(data->peak()->memStacks()) << " stacks";
+
+    // Begin dotGraph
 #ifdef HAVE_KGRAPHVIEWER
     if (m_graphViewer) {
-        showDotGraph(QPair<TreeLeafItem*,SnapshotItem*>(0, m_data->peak()));
+        showDotGraph(QPair<TreeLeafItem*,SnapshotItem*>(0, data->peak()));
         m_zoomIn->setEnabled(true);
         m_zoomOut->setEnabled(true);
         m_focusExpensive->setEnabled(true);
     }
 #endif
 
-    //BEGIN KDChart
+    // Copied from the initializer-list
+    Chart* chart = new Chart(this);
+    QLabel* header = new QLabel(this);
+    TotalCostModel* totalCostModel = new TotalCostModel(chart);
+    DetailedCostModel* detailedCostModel = new DetailedCostModel(chart);
+    Legend* legend = new Legend(chart);
+    DataTreeModel* dataTreeModel = new DataTreeModel(chart);
+    m_dataTreeModels.append(dataTreeModel);
+    FilteredDataTreeModel* filteredDataTreeModel = new FilteredDataTreeModel(dataTreeModel);
+    m_filteredDataTreeModels.append(filteredDataTreeModel);
+
+    // Copied from Ctor
+    chart->setGlobalLeadingRight(10);
+    chart->setGlobalLeadingLeft(10);
+    chart->setGlobalLeadingTop(20);
+    connect(chart, SIGNAL(customContextMenuRequested(QPoint)),
+            this, SLOT(chartContextMenuRequested(QPoint)));
+    chart->setContextMenuPolicy(Qt::CustomContextMenu);
+
+    legend->setPosition(Position(KDChartEnums::PositionFloating));
+    legend->setTitleText("");
+    legend->setAlignment(Qt::AlignVCenter | Qt::AlignLeft);
+    legend->setSortOrder(Qt::DescendingOrder);
+
+    chart->addLegend(legend);
+
+    //NOTE: this has to be set _after_ the legend was added to the chart...
+    TextAttributes att = legend->textAttributes();
+    att.setAutoShrink(true);
+    att.setFontSize( Measure(12) );
+    QFont font("monospace");
+    font.setStyleHint(QFont::TypeWriter);
+    att.setFont(font);
+    legend->setTextAttributes(att);
+    legend->setTextAlignment(Qt::AlignLeft);
+    legend->hide();
+
+    connect(ui.filterDataTree, SIGNAL(textChanged(QString)),
+            filteredDataTreeModel, SLOT(setFilter(QString)));
+    ui.dataTreeView->setModel(filteredDataTreeModel);
+    connect(ui.dataTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+            this, SLOT(treeSelectionChanged(QModelIndex,QModelIndex)));
+
+    // Begin chart
     KColorScheme scheme(QPalette::Active, KColorScheme::Window);
     QPen foreground(scheme.foreground().color());
 
     //Begin Legend
-    BackgroundAttributes bkgAtt = m_legend->backgroundAttributes();
+    BackgroundAttributes bkgAtt = legend->backgroundAttributes();
     QColor background = scheme.background(KColorScheme::AlternateBackground).color();
     background.setAlpha(200);
     bkgAtt.setBrush(QBrush(background));
     bkgAtt.setVisible(true);
-    m_legend->setBackgroundAttributes(bkgAtt);
-    TextAttributes txtAttrs = m_legend->textAttributes();
+    legend->setBackgroundAttributes(bkgAtt);
+    TextAttributes txtAttrs = legend->textAttributes();
     txtAttrs.setPen(foreground);
-    m_legend->setTextAttributes(txtAttrs);
-
-    //BEGIN Header
-    {
-        m_header->setAlignment(Qt::AlignCenter);
-        updateHeader();
-    }
+    legend->setTextAttributes(txtAttrs);
 
-    setWindowTitle(i18n("Massif Visualizer - evaluation of %1 (%2)", m_data->cmd(), m_currentFile.fileName()));
+    header->setAlignment(Qt::AlignCenter);
 
-    //BEGIN TotalDiagram
-    m_totalDiagram = new Plotter;
+    // Begin totalDiagram
+    Plotter* totalDiagram = new Plotter;
     m_toggleTotal->setEnabled(true);
-    m_totalDiagram->setAntiAliasing(true);
+    totalDiagram->setAntiAliasing(true);
 
-    CartesianAxis* bottomAxis = new CartesianAxis(m_totalDiagram);
+    CartesianAxis* bottomAxis = new CartesianAxis(totalDiagram);
     TextAttributes axisTextAttributes = bottomAxis->textAttributes();
     axisTextAttributes.setPen(foreground);
     axisTextAttributes.setFontSize(Measure(10));
@@ -540,177 +563,253 @@ void MainWindow::parserFinished(const KUrl& file, FileData* data)
     axisTitleTextAttributes.setPen(foreground);
     axisTitleTextAttributes.setFontSize(Measure(12));
     bottomAxis->setTitleTextAttributes(axisTitleTextAttributes);
-    bottomAxis->setTitleText(i18n("time in %1", m_data->timeUnit()));
+    bottomAxis->setTitleText(i18n("time in %1", data->timeUnit()));
     bottomAxis->setPosition ( CartesianAxis::Bottom );
-    m_totalDiagram->addAxis(bottomAxis);
+    totalDiagram->addAxis(bottomAxis);
 
-    CartesianAxis* rightAxis = new CartesianAxis(m_totalDiagram);
+    CartesianAxis* rightAxis = new CartesianAxis(totalDiagram);
     rightAxis->setTextAttributes(axisTextAttributes);
     rightAxis->setTitleTextAttributes(axisTitleTextAttributes);
     rightAxis->setTitleText(i18n("memory heap size in kilobytes"));
     rightAxis->setPosition ( CartesianAxis::Right );
-    m_totalDiagram->addAxis(rightAxis);
+    totalDiagram->addAxis(rightAxis);
 
-    m_totalCostModel->setSource(m_data);
-    m_totalDiagram->setModel(m_totalCostModel);
+    totalCostModel->setSource(data);
+    totalDiagram->setModel(totalCostModel);
 
-    CartesianCoordinatePlane* coordinatePlane = dynamic_cast<CartesianCoordinatePlane*>(m_chart->coordinatePlane());
+    CartesianCoordinatePlane* coordinatePlane = dynamic_cast<CartesianCoordinatePlane*>(chart->coordinatePlane());
     Q_ASSERT(coordinatePlane);
-    coordinatePlane->addDiagram(m_totalDiagram);
+    coordinatePlane->addDiagram(totalDiagram);
 
     GridAttributes gridAttributes = coordinatePlane->gridAttributes(Qt::Horizontal);
     gridAttributes.setAdjustBoundsToGrid(false, false);
     coordinatePlane->setGridAttributes(Qt::Horizontal, gridAttributes);
 
-    m_legend->addDiagram(m_totalDiagram);
-    connect(m_totalDiagram, SIGNAL(clicked(QModelIndex)),
+    legend->addDiagram(totalDiagram);
+    connect(totalDiagram, SIGNAL(clicked(QModelIndex)),
             this, SLOT(totalItemClicked(QModelIndex)));
 
-    //BEGIN DetailedDiagram
-    m_detailedDiagram = new Plotter;
+    // Begin detailedDiagram
+    Plotter* detailedDiagram = new Plotter;
     m_toggleDetailed->setEnabled(true);
-    m_detailedDiagram->setAntiAliasing(true);
-    m_detailedDiagram->setType(KDChart::Plotter::Stacked);
-
-    m_detailedCostModel->setSource(m_data);
-    m_detailedDiagram->setModel(m_detailedCostModel);
+    detailedDiagram->setAntiAliasing(true);
+    detailedDiagram->setType(KDChart::Plotter::Stacked);
 
-    updatePeaks();
+    detailedCostModel->setSource(data);
+    detailedDiagram->setModel(detailedCostModel);
 
-    m_chart->coordinatePlane()->addDiagram(m_detailedDiagram);
-    connect(m_detailedDiagram, SIGNAL(clicked(QModelIndex)),
+    chart->coordinatePlane()->addDiagram(detailedDiagram);
+    connect(detailedDiagram, SIGNAL(clicked(QModelIndex)),
             this, SLOT(detailedItemClicked(QModelIndex)));
 
-    m_legend->addDiagram(m_detailedDiagram);
-
-    //BEGIN Legend
-    m_legend->show();
+    legend->addDiagram(detailedDiagram);
+    legend->show();
 
-    //BEGIN TreeView
-    m_dataTreeModel->setSource(m_data);
+    // Begin treeView
+    dataTreeModel->setSource(data);
     m_selectPeak->setEnabled(true);
 
-    //BEGIN RecentFiles
-    m_recentFiles->addUrl(m_currentFile);
+    // Create a new tab with everything in it.
+    QTabWidget* newMassifFileTabWidget = new QTabWidget(this);
+    newMassifFileTabWidget->setTabPosition(QTabWidget::South);
+    // First sub-tab
+    newMassifFileTabWidget->addTab(new QWidget, QIcon::fromTheme("office-chart-area-stacked"), i18n("&Evolution of Memory Consumption"));
+    newMassifFileTabWidget->widget(0)->setLayout(new QVBoxLayout);
+    newMassifFileTabWidget->widget(0)->layout()->addWidget(header);
+    newMassifFileTabWidget->widget(0)->layout()->addWidget(chart);    
+
+#ifdef HAVE_KGRAPHVIEWER
+    if (m_graphViewerPart) {
+        // Second sub-tab if kgraphviewer is installed and working.
+        connect(m_graphViewerPart, SIGNAL(graphLoaded()), this, SLOT(slotGraphLoaded()));
+        newMassifFileTabWidget->addTab(graphViewerPart->widget(), QIcon::fromTheme("kgraphviewer"), i18n("&Detailed Snapshot Analysis"));
+        connect(newMassifFileTabWidget, SIGNAL(currentChanged(int)), this, SLOT(slotTabChanged(int)));
+    }
+#endif
+
+    ui.filesTabWidget->addTab(newMassifFileTabWidget, QIcon::fromTheme("application-vnd.oasis.opendocument.chart"), file.fileName());
+    ui.filesTabWidget->setCurrentIndex(ui.filesTabWidget->count() - 1);
+
+    updateHeader();
+    updatePeaks();
 
     ui.stackedWidget->setCurrentWidget(ui.displayPage);
 }
 
 void MainWindow::parserError(const QString& title, const QString& error)
 {
+    // NOTE (arnold): if this line is before the dialog, all the dialogs
+    // will spawn after the loading of all the files has finished.
+    m_isParseWorkerRunning = false;
+
     KMessageBox::error(this, error, title);
+
+    if (ui.filesTabWidget->count()) {
+        ui.stackedWidget->setCurrentWidget(ui.displayPage);
+    } else {
+        ui.stackedWidget->setCurrentWidget(ui.openPage);
+    }
 }
 
 void MainWindow::updateHeader()
-{
-    const QString app = m_data->cmd().split(' ', QString::SkipEmptyParts).first();
+{   
+    const QString app = currentFileData()->cmd().split(' ', QString::SkipEmptyParts).first();
 
-    m_header->setText(QString("<b>%1</b><br /><i>%2</i>")
+    currentHeader()->setText(QString("<b>%1</b><br /><i>%2</i>")
                         .arg(i18n("Memory consumption of %1", app))
-                        .arg(i18n("Peak of %1 at snapshot #%2", prettyCost(m_data->peak()->cost()), m_data->peak()->number()))
+                        .arg(i18n("Peak of %1 at snapshot #%2", prettyCost(currentFileData()->peak()->cost()), currentFileData()->peak()->number()))
     );
-    m_header->setToolTip(i18n("Command: %1\nValgrind Options: %2", m_data->cmd(), m_data->description()));
+    currentHeader()->setToolTip(i18n("Command: %1\nValgrind Options: %2", currentFileData()->cmd(), currentFileData()->description()));
 }
 
 void MainWindow::treeSelectionChanged(const QModelIndex& now, const QModelIndex& before)
 {
-    if (m_changingSelections || !m_data) {
+    if (currentChangingSelections() || !currentFileData()) {
         return;
     }
 
     if (now == before) {
         return;
     }
-    m_changingSelections = true;
+    setCurrentChangingSelections(true);
 
-    const QPair< TreeLeafItem*, SnapshotItem* >& item = m_dataTreeModel->itemForIndex(
-       m_dataTreeFilterModel->mapToSource(now)
+    const QPair< TreeLeafItem*, SnapshotItem* >& item = currentDataTreeModel()->itemForIndex(
+       currentFilteredDataTreeModel()->mapToSource(now)
     );
 
     if (now.parent().isValid()) {
-        m_detailedCostModel->setSelection(m_detailedCostModel->indexForItem(item));
-        m_totalCostModel->setSelection(QModelIndex());
+        currentDetailedCostModel()->setSelection(currentDetailedCostModel()->indexForItem(item));
+        currentTotalCostModel()->setSelection(QModelIndex());
     } else {
-        m_totalCostModel->setSelection(m_totalCostModel->indexForItem(item));
-        m_detailedCostModel->setSelection(QModelIndex());
+        currentTotalCostModel()->setSelection(currentTotalCostModel()->indexForItem(item));
+        currentDetailedCostModel()->setSelection(QModelIndex());
     }
 
-    m_chart->update();
+    currentChart()->update();
+
 #ifdef HAVE_KGRAPHVIEWER
     if (m_graphViewer) {
         showDotGraph(item);
     }
 #endif
 
-    m_changingSelections = false;
+    setCurrentChangingSelections(false);
 }
 
 void MainWindow::detailedItemClicked(const QModelIndex& idx)
 {
-    if (m_changingSelections || !m_data) {
+    if (currentChangingSelections() || !currentFileData()) {
         return;
     }
 
-    m_changingSelections = true;
+    setCurrentChangingSelections(true);
 
-    m_detailedCostModel->setSelection(idx);
-    m_totalCostModel->setSelection(QModelIndex());
+    currentDetailedCostModel()->setSelection(idx);
+    currentTotalCostModel()->setSelection(QModelIndex());
 
     // hack: the ToolTip will only be queried by KDChart and that one uses the
     // left index, but we want it to query the right one
-    const QModelIndex _idx = m_detailedCostModel->index(idx.row() + 1, idx.column(), idx.parent());
+    const QModelIndex _idx = currentDetailedCostModel()->index(idx.row() + 1, idx.column(), idx.parent());
     ui.dataTreeView->selectionModel()->clearSelection();
-    QPair< TreeLeafItem*, SnapshotItem* > item = m_detailedCostModel->itemForIndex(_idx);
-    const QModelIndex& newIndex = m_dataTreeFilterModel->mapFromSource(
-        m_dataTreeModel->indexForItem(item)
+    QPair< TreeLeafItem*, SnapshotItem* > item = currentDetailedCostModel()->itemForIndex(_idx);
+    const QModelIndex& newIndex = currentFilteredDataTreeModel()->mapFromSource(
+        currentDataTreeModel()->indexForItem(item)
     );
     ui.dataTreeView->selectionModel()->setCurrentIndex(newIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows);
     ui.dataTreeView->scrollTo(ui.dataTreeView->selectionModel()->currentIndex());
 
-    m_chart->update();
+    currentChart()->update();
 #ifdef HAVE_KGRAPHVIEWER
     if (m_graphViewer) {
         showDotGraph(item);
     }
 #endif
 
-    m_changingSelections = false;
+    setCurrentChangingSelections(false);
 }
 
 void MainWindow::totalItemClicked(const QModelIndex& idx_)
 {
-    if (m_changingSelections || !m_data) {
+    if (currentChangingSelections() || !currentFileData()) {
         return;
     }
 
-    m_changingSelections = true;
+    setCurrentChangingSelections(true);
 
     QModelIndex idx = idx_.model()->index(idx_.row() + 1, idx_.column(), idx_.parent());
 
-    m_detailedCostModel->setSelection(QModelIndex());
-    m_totalCostModel->setSelection(idx);
+    currentDetailedCostModel()->setSelection(QModelIndex());
+    currentTotalCostModel()->setSelection(idx);
 
-    QPair< TreeLeafItem*, SnapshotItem* > item = m_totalCostModel->itemForIndex(idx);
+    QPair< TreeLeafItem*, SnapshotItem* > item = currentTotalCostModel()->itemForIndex(idx);
 
     ui.dataTreeView->selectionModel()->clearSelection();
-    const QModelIndex& newIndex = m_dataTreeFilterModel->mapFromSource(
-        m_dataTreeModel->indexForItem(item)
+    const QModelIndex& newIndex = currentFilteredDataTreeModel()->mapFromSource(
+        currentDataTreeModel()->indexForItem(item)
     );
     ui.dataTreeView->selectionModel()->setCurrentIndex(newIndex, QItemSelectionModel::Select | QItemSelectionModel::Rows);
     ui.dataTreeView->scrollTo(ui.dataTreeView->selectionModel()->currentIndex());
 
-    m_chart->update();
+    currentChart()->update();
 
-    m_changingSelections = false;
+    setCurrentChangingSelections(false);
 }
 
-void MainWindow::closeFile()
+void MainWindow::closeCurrentFile()
 {
-    if (!m_data) {
+    if (!currentFileData()) {
         return;
     }
 
-    ui.stackedWidget->setCurrentWidget(ui.openPage);
+    currentDataTreeModel()->setSource(0);
+    currentFilteredDataTreeModel()->setFilter("");
+    currentDetailedCostModel()->setSource(0);
+    currentTotalCostModel()->setSource(0);
+
+    m_toggleDetailed->setEnabled(false);
+    m_toggleDetailed->setChecked(true);
+
+    foreach (CartesianAxis* axis, currentDetailedDiagram()->axes()) {
+        currentDetailedDiagram()->takeAxis(axis);
+        axis->deleteLater();
+    }
+    currentDetailedDiagram()->deleteLater();
+
+    m_toggleTotal->setEnabled(false);
+    m_toggleTotal->setChecked(true);
+    foreach (CartesianAxis* axis, currentTotalDiagram()->axes()) {
+        currentTotalDiagram()->takeAxis(axis);
+        axis->deleteLater();
+    }
+    currentTotalDiagram()->deleteLater();
+
+    currentChart()->deleteLater();
+    currentTotalCostModel()->deleteLater();
+    currentDetailedCostModel()->deleteLater();
+
+    // Tab is now removed
+    int tabToCloseIndex = ui.filesTabWidget->currentIndex();
+    ui.filesTabWidget->widget(tabToCloseIndex)->deleteLater();
+    ui.filesTabWidget->removeTab(tabToCloseIndex);
+
+    if (!ui.filesTabWidget->count()) {
+        actionCollection()->action("file_reload")->setEnabled(false);
+        m_close->setEnabled(false);
+        m_print->setEnabled(false);
+        m_toggleDetailed->setEnabled(false);
+        m_toggleTotal->setEnabled(false);
+        m_selectPeak->setEnabled(false);
+        ui.stackedWidget->setCurrentWidget(ui.openPage);
+    }
+
+    m_openedFiles.remove(tabToCloseIndex);
+    delete m_fileDataVector[tabToCloseIndex];
+    m_fileDataVector.remove(tabToCloseIndex);
+    delete m_filteredDataTreeModels[tabToCloseIndex];
+    m_filteredDataTreeModels.remove(tabToCloseIndex);
+    m_dataTreeModels[tabToCloseIndex]->setSource(0);
+    delete m_dataTreeModels[tabToCloseIndex];
+    m_dataTreeModels.remove(tabToCloseIndex);
 
 #ifdef HAVE_KGRAPHVIEWER
     if (m_dotGenerator) {
@@ -733,64 +832,25 @@ void MainWindow::closeFile()
     m_lastDotItem.second = 0;
 #endif
 
-    m_close->setEnabled(false);
-    m_print->setEnabled(false);
-
     kDebug() << "closing file";
-
-    m_chart->replaceCoordinatePlane(new CartesianCoordinatePlane);
-    m_legend->removeDiagrams();
-    m_legend->hide();
-    m_header->setText("");
-
-    m_toggleDetailed->setEnabled(false);
-    m_toggleDetailed->setChecked(true);
-    foreach(CartesianAxis* axis, m_detailedDiagram->axes()) {
-        m_detailedDiagram->takeAxis(axis);
-        delete axis;
-    }
-    delete m_detailedDiagram;
-    m_detailedDiagram = 0;
-
-    m_toggleTotal->setEnabled(false);
-    m_toggleTotal->setChecked(true);
-    foreach(CartesianAxis* axis, m_totalDiagram->axes()) {
-        m_totalDiagram->takeAxis(axis);
-        delete axis;
-    }
-    delete m_totalDiagram;
-    m_totalDiagram = 0;
-
-    m_dataTreeModel->setSource(0);
-    m_dataTreeFilterModel->setFilter("");
-    m_detailedCostModel->setSource(0);
-    m_totalCostModel->setSource(0);
-
-    m_selectPeak->setEnabled(false);
-
-    delete m_data;
-    m_data = 0;
-    m_currentFile.clear();
-
-    setWindowTitle(i18n("Massif Visualizer"));
 }
 
 void MainWindow::showDetailedGraph(bool show)
 {
-    Q_ASSERT(m_data);
-    Q_ASSERT(m_detailedDiagram);
-    m_detailedDiagram->setHidden(!show);
+    Q_ASSERT(currentFileData());
+    Q_ASSERT(currentDetailedDiagram());
+    currentDetailedDiagram()->setHidden(!show);
     m_toggleDetailed->setChecked(show);
-    m_chart->update();
+    currentChart()->update();
 }
 
 void MainWindow::showTotalGraph(bool show)
 {
-    Q_ASSERT(m_data);
-    Q_ASSERT(m_totalDiagram);
-    m_totalDiagram->setHidden(!show);
+    Q_ASSERT(currentFileData());
+    Q_ASSERT(currentTotalDiagram());
+    currentTotalDiagram()->setHidden(!show);
     m_toggleTotal->setChecked(show);
-    m_chart->update();
+    currentChart()->update();
 }
 
 #ifdef HAVE_KGRAPHVIEWER
@@ -798,11 +858,11 @@ void MainWindow::slotTabChanged(int index)
 {
     toolBar("chartToolBar")->setVisible(index == 0);
     foreach(QAction* action, toolBar("chartToolBar")->actions()) {
-        action->setEnabled(m_data && index == 0);
+        action->setEnabled(currentFileData() && index == 0);
     }
     toolBar("callgraphToolBar")->setVisible(index == 1);
     foreach(QAction* action, toolBar("callgraphToolBar")->actions()) {
-        action->setEnabled(m_data && index == 1);
+        action->setEnabled(currentFileData() && index == 1);
     }
     if (index == 1) {
         // if we parsed a dot graph we might want to show it now
@@ -835,9 +895,9 @@ void MainWindow::showDotGraph(const QPair<TreeLeafItem*, SnapshotItem*>& item)
         return;
     }
     if (item.second) {
-        m_dotGenerator.reset(new DotGraphGenerator(item.second, m_data->timeUnit(), this));
+        m_dotGenerator.reset(new DotGraphGenerator(item.second, currentFileData()->timeUnit(), this));
     } else {
-        m_dotGenerator.reset(new DotGraphGenerator(item.first, m_data->timeUnit(), this));
+        m_dotGenerator.reset(new DotGraphGenerator(item.first, currentFileData()->timeUnit(), this));
     }
     connect(m_dotGenerator.data(), SIGNAL(finished()), SLOT(showDotGraph()));
     m_dotGenerator->start();
@@ -892,20 +952,20 @@ void MainWindow::focusExpensiveGraphNode()
 
 void MainWindow::selectPeakSnapshot()
 {
-    Q_ASSERT(m_data);
+    Q_ASSERT(currentFileData());
 
     ui.dataTreeView->selectionModel()->clearSelection();
     ui.dataTreeView->selectionModel()->setCurrentIndex(
-        m_dataTreeFilterModel->mapFromSource(
-            m_dataTreeModel->indexForSnapshot(m_data->peak())
+        currentFilteredDataTreeModel()->mapFromSource(
+            currentDataTreeModel()->indexForSnapshot(currentFileData()->peak())
         ), QItemSelectionModel::Select | QItemSelectionModel::Rows
     );
 }
 
 void MainWindow::setStackNum(int num)
 {
-    if (m_detailedCostModel) {
-        m_detailedCostModel->setMaximumDatasetCount(num);
+    if (currentDetailedCostModel()) {
+        currentDetailedCostModel()->setMaximumDatasetCount(num);
         updateDetailedPeaks();
     }
 }
@@ -915,10 +975,10 @@ void MainWindow::updatePeaks()
     KColorScheme scheme(QPalette::Active, KColorScheme::Window);
     QPen foreground(scheme.foreground().color());
 
-    if (m_data->peak()) {
-        const QModelIndex peak = m_totalCostModel->peak();
+    if (currentFileData()->peak()) {
+        const QModelIndex peak = currentTotalCostModel()->peak();
         Q_ASSERT(peak.isValid());
-        markPeak(m_totalDiagram, peak, m_data->peak()->cost(), foreground);
+        markPeak(currentTotalDiagram(), peak, currentFileData()->peak()->cost(), foreground);
     }
     updateDetailedPeaks();
 }
@@ -928,12 +988,12 @@ void MainWindow::updateDetailedPeaks()
     KColorScheme scheme(QPalette::Active, KColorScheme::Window);
     QPen foreground(scheme.foreground().color());
 
-    QMap< QModelIndex, TreeLeafItem* > peaks = m_detailedCostModel->peaks();
+    QMap< QModelIndex, TreeLeafItem* > peaks = currentDetailedCostModel()->peaks();
     QMap< QModelIndex, TreeLeafItem* >::const_iterator it = peaks.constBegin();
     while (it != peaks.constEnd()) {
         const QModelIndex peak = it.key();
         Q_ASSERT(peak.isValid());
-        markPeak(m_detailedDiagram, peak, it.value()->cost(), foreground);
+        markPeak(currentDetailedDiagram(), peak, it.value()->cost(), foreground);
         ++it;
     }
 }
@@ -952,7 +1012,7 @@ void MainWindow::allocatorsChanged()
     }
     cfg.sync();
 
-    if (m_data) {
+    if (currentFileData()) {
         reload();
     }
 }
@@ -1005,11 +1065,12 @@ void MainWindow::allocatorViewContextMenuRequested(const QPoint& pos)
 
 void MainWindow::dataTreeContextMenuRequested(const QPoint& pos)
 {
-    const QModelIndex idx = m_dataTreeFilterModel->mapToSource(
+    const QModelIndex idx = currentFilteredDataTreeModel()->mapToSource(
                                 ui.dataTreeView->indexAt(pos));
     if (!idx.isValid()) {
         return;
     }
+    setCurrentChangingSelections(false);
 
     if (!idx.parent().isValid()) {
         // snapshot item
@@ -1017,7 +1078,7 @@ void MainWindow::dataTreeContextMenuRequested(const QPoint& pos)
     }
 
     QMenu menu;
-    TreeLeafItem* item = m_dataTreeModel->itemForIndex(idx).first;
+    TreeLeafItem* item = currentDataTreeModel()->itemForIndex(idx).first;
     Q_ASSERT(item);
     prepareActions(&menu, item);
     menu.exec(ui.dataTreeView->mapToGlobal(pos));
@@ -1025,16 +1086,16 @@ void MainWindow::dataTreeContextMenuRequested(const QPoint& pos)
 
 void MainWindow::chartContextMenuRequested(const QPoint& pos)
 {
-    const QPoint dPos = m_detailedDiagram->mapFromGlobal(m_chart->mapToGlobal(pos));
+    const QPoint dPos = currentDetailedDiagram()->mapFromGlobal(currentChart()->mapToGlobal(pos));
 
-    const QModelIndex idx = m_detailedDiagram->indexAt(dPos);
+    const QModelIndex idx = currentDetailedDiagram()->indexAt(dPos);
     if (!idx.isValid()) {
         return;
     }
     // hack: the ToolTip will only be queried by KDChart and that one uses the
     // left index, but we want it to query the right one
-    const QModelIndex _idx = m_detailedCostModel->index(idx.row() + 1, idx.column(), idx.parent());
-    QPair< TreeLeafItem*, SnapshotItem* > item = m_detailedCostModel->itemForIndex(_idx);
+    const QModelIndex _idx = currentDetailedCostModel()->index(idx.row() + 1, idx.column(), idx.parent());
+    QPair< TreeLeafItem*, SnapshotItem* > item = currentDetailedCostModel()->itemForIndex(_idx);
 
     if (!item.first) {
         return;
@@ -1043,7 +1104,7 @@ void MainWindow::chartContextMenuRequested(const QPoint& pos)
     QMenu menu;
     menu.addAction(m_markCustomAllocator);
     prepareActions(&menu, item.first);
-    menu.exec(m_detailedDiagram->mapToGlobal(dPos));
+    menu.exec(currentDetailedDiagram()->mapToGlobal(dPos));
 }
 
 void MainWindow::prepareActions(QMenu* menu, TreeLeafItem* item)
@@ -1067,12 +1128,12 @@ void MainWindow::prepareActions(QMenu* menu, TreeLeafItem* item)
 
 void MainWindow::slotHideFunction()
 {
-    m_detailedCostModel->hideFunction(m_hideFunction->data().value<TreeLeafItem*>());
+    currentDetailedCostModel()->hideFunction(m_hideFunction->data().value<TreeLeafItem*>());
 }
 
 void MainWindow::slotHideOtherFunctions()
 {
-    m_detailedCostModel->hideOtherFunctions(m_hideOtherFunctions->data().value<TreeLeafItem*>());
+    currentDetailedCostModel()->hideOtherFunctions(m_hideOtherFunctions->data().value<TreeLeafItem*>());
 }
 
 void MainWindow::slotShortenTemplates(bool shorten)
@@ -1087,7 +1148,7 @@ void MainWindow::slotShortenTemplates(bool shorten)
 
 void MainWindow::showPrintPreviewDialog()
 {
-    Q_ASSERT(m_data);
+    Q_ASSERT(currentFileData());
 
     QPrinter printer;
     QPrintPreviewDialog *ppd = new QPrintPreviewDialog(&printer, this);
@@ -1102,8 +1163,169 @@ void  MainWindow::printFile(QPrinter *printer)
 {
     QPainter painter;
     painter.begin(printer);
-    m_chart->paint(&painter, printer->pageRect());
+    currentChart()->paint(&painter, printer->pageRect());
     painter.end();
 }
 
+QLabel* MainWindow::currentHeader()
+{
+    // The header is the first item in the vertical layout of the first tab
+    if (ui.filesTabWidget->count()) {
+        return static_cast<QLabel*>(static_cast<QTabWidget*>(ui.filesTabWidget->currentWidget())->widget(0)->layout()->itemAt(0)->widget());
+    } else {
+        return 0;
+    }
+}
+
+Chart* MainWindow::currentChart()
+{
+    // The chart is the second item in the vertical layout of the first tab
+    if (ui.filesTabWidget->count()) {
+        return static_cast<Chart*>(static_cast<QTabWidget*>(ui.filesTabWidget->currentWidget())->widget(0)->layout()->itemAt(1)->widget());
+    } else {
+        return 0;
+    }
+}
+
+KDChart::Plotter* MainWindow::currentDetailedDiagram()
+{
+    // The detailedDiagram is the second diagram of the chart
+    if (currentChart()) {
+        return static_cast<Plotter*>(currentChart()->coordinatePlane()->diagrams().at(1));
+    } else {
+        return 0;
+    }
+}
+
+DetailedCostModel* MainWindow::currentDetailedCostModel()
+{
+    if (currentDetailedDiagram()) {
+        return static_cast<DetailedCostModel*>(currentDetailedDiagram()->model());
+    } else {
+        return 0;
+    }
+}
+
+KDChart::Plotter* MainWindow::currentTotalDiagram()
+{
+    if (currentChart()) {
+        return static_cast<Plotter*>(currentChart()->coordinatePlane()->diagrams().at(0));
+    } else {
+        return 0;
+    }
+}
+
+TotalCostModel* MainWindow::currentTotalCostModel()
+{
+    if (currentTotalDiagram()) {
+        return static_cast<TotalCostModel*>(currentTotalDiagram()->model());
+    } else {
+        return 0;
+    }
+}
+
+DataTreeModel* MainWindow::currentDataTreeModel()
+{
+    if (m_dataTreeModels.size() && ui.filesTabWidget->count()) {
+        return m_dataTreeModels[ui.filesTabWidget->currentIndex()];
+    } else {
+        return 0;
+    }
+}
+
+FilteredDataTreeModel* MainWindow::currentFilteredDataTreeModel()
+{
+    if (m_filteredDataTreeModels.size() && ui.filesTabWidget->count()) {
+        return m_filteredDataTreeModels[ui.filesTabWidget->currentIndex()];
+    } else {
+        return 0;
+    }
+}
+
+FileData* MainWindow::currentFileData()
+{
+    if (m_fileDataVector.size() && ui.filesTabWidget->count()) {
+        return m_fileDataVector[ui.filesTabWidget->currentIndex()];
+    } else {
+        return 0;
+    }
+}
+
+KUrl MainWindow::currentFile()
+{
+    if (m_dataTreeModels.size() && ui.filesTabWidget->count()) {
+        return m_openedFiles[ui.filesTabWidget->currentIndex()];
+    } else {
+        return KUrl();
+    }
+}
+
+void MainWindow::fileTabChanged(int index)
+{
+    Q_UNUSED(index)
+
+    updateWindowTitle();
+    ui.dataTreeView->setModel(currentFilteredDataTreeModel());
+
+    // FIXME (arnold): this connection shouldn't be necessary
+    connect(ui.dataTreeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
+            this, SLOT(treeSelectionChanged(QModelIndex,QModelIndex)));
+
+    // Is there is any tab left ?
+    if (ui.filesTabWidget->count()) {
+        m_toggleDetailed->setChecked(!currentDetailedDiagram()->isHidden());
+        m_toggleTotal->setChecked(!currentTotalDiagram()->isHidden());
+    }
+}
+
+void MainWindow::updateWindowTitle()
+{
+    if (ui.filesTabWidget->count()) {
+        setWindowTitle(i18n("Massif Visualizer - evaluation of %1 (%2)", currentFileData()->cmd(), currentFile().fileName()));
+    } else {
+        setWindowTitle(i18n("Massif Visualizer"));
+    }
+}
+
+bool MainWindow::currentChangingSelections()
+{
+    if (m_changingSelectionsVector.size() && ui.filesTabWidget->count()) {
+        return m_changingSelectionsVector[ui.filesTabWidget->currentIndex()];
+    } else {
+        return false;
+    }
+}
+
+void MainWindow::setCurrentChangingSelections(bool changingSelections)
+{
+    if (m_dataTreeModels.size() && ui.filesTabWidget->count()) {
+        m_changingSelectionsVector[ui.filesTabWidget->currentIndex()] = changingSelections;
+    }
+}
+
+void MainWindow::openFileLater()
+{
+    // No more file to open.
+    if (!m_filesToOpenList.count()) {
+        return;
+    }
+
+    if (m_isParseWorkerRunning) {
+        // FIXME (arnold): replace magic number by constant.
+        QTimer::singleShot(50, this, SLOT(openFileLater()));
+    } else {
+        // Parser if free
+        openFile(m_filesToOpenList.first(), m_filesToOpenReloadList.first());
+        m_filesToOpenList.removeFirst();
+        m_filesToOpenReloadList.removeFirst();
+    }
+}
+
+void MainWindow::openFileLater(const KUrl &file, bool reload)
+{
+    m_filesToOpenList.append(file);
+    m_filesToOpenReloadList.append(reload);
+    openFileLater();
+}
+
 #include "mainwindow.moc"
diff --git a/app/mainwindow.h b/app/mainwindow.h
index 2acc6a8..cf948f5 100644
--- a/app/mainwindow.h
+++ b/app/mainwindow.h
@@ -2,6 +2,7 @@
    This file is part of Massif Visualizer
 
    Copyright 2010 Milian Wolff <mail@milianw.de>
+   Copyright 2013 Arnold Dumas <contact@arnolddumas.com>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
@@ -26,6 +27,7 @@
 #include <KParts/MainWindow>
 
 #include <QPrintPreviewDialog>
+#include <QList>
 
 #include "ui_mainwindow.h"
 
@@ -84,8 +86,9 @@ public slots:
 
     /**
      * Opens @p file as massif output file and visualize it.
+     * If the @p file is already opened and ones want to reload it, then set @p reload to true.
      */
-    void openFile(const KUrl& file);
+    void openFile(const KUrl& file, bool reload = false);
 
     /**
      * reload currently opened file
@@ -95,7 +98,7 @@ public slots:
     /**
      * Close currently opened file.
      */
-    void closeFile();
+    void closeCurrentFile();
 
     /**
      * Depending on @p show, the total cost graph is shown or hidden.
@@ -118,6 +121,18 @@ public slots:
     void printFile(QPrinter *printer);
 
 private slots:
+    /**
+     * @brief openFileLater
+     */
+    void openFileLater();
+
+    /**
+     * @brief openFileLater
+     * @param file
+     * @param reload
+     */
+    void openFileLater(const KUrl& file, bool reload);
+
     void preferences();
     void settingsChanged();
 
@@ -127,6 +142,8 @@ private slots:
     void selectPeakSnapshot();
     void setStackNum(int num);
 
+    void fileTabChanged(int index);
+
 #ifdef HAVE_KGRAPHVIEWER
     void showDotGraph();
     void slotTabChanged(int index);
@@ -157,34 +174,44 @@ private slots:
     void parserError(const QString& title, const QString& error);
 
 private:
+    /**
+     * Returns the current something based on the active tab.
+     * They either return a valid pointer to the something or a
+     * pointer null pointer if no tab is opened at the moment.
+     */
+    QLabel* currentHeader();
+    KDChart::Chart* currentChart();
+    KDChart::Plotter* currentTotalDiagram();
+    TotalCostModel* currentTotalCostModel();
+    KDChart::Plotter* currentDetailedDiagram();
+    DetailedCostModel* currentDetailedCostModel();
+    DataTreeModel* currentDataTreeModel();
+    FilteredDataTreeModel* currentFilteredDataTreeModel();
+    FileData* currentFileData();
+    KUrl currentFile();
+    bool currentChangingSelections();
+    void setCurrentChangingSelections(bool changingSelections);
+
     void showDotGraph(const QPair<TreeLeafItem*, SnapshotItem*>& item);
     void updateHeader();
+    void updateWindowTitle();
     void updatePeaks();
     void updateDetailedPeaks();
     void prepareActions(QMenu* menu, TreeLeafItem* item);
 
     Ui::MainWindow ui;
-    KDChart::Chart* m_chart;
-    QLabel* m_header;
-    KAction* m_toggleTotal;
-    KDChart::Plotter* m_totalDiagram;
-    TotalCostModel* m_totalCostModel;
 
+    KAction* m_toggleTotal;
     KAction* m_toggleDetailed;
-    KDChart::Plotter* m_detailedDiagram;
-    DetailedCostModel* m_detailedCostModel;
-
-    KDChart::Legend* m_legend;
-
-    DataTreeModel* m_dataTreeModel;
-    FilteredDataTreeModel* m_dataTreeFilterModel;
-    FileData* m_data;
-    KUrl m_currentFile;
     KAction* m_selectPeak;
-
     KRecentFilesAction* m_recentFiles;
 
-    bool m_changingSelections;
+    QVector<FileData*> m_fileDataVector;
+    QVector<KUrl> m_openedFiles;
+    QVector<DataTreeModel*> m_dataTreeModels;
+    QVector<FilteredDataTreeModel*> m_filteredDataTreeModels;
+    QVector<bool> m_changingSelectionsVector;
+
 #ifdef HAVE_KGRAPHVIEWER
     KParts::ReadOnlyPart* m_graphViewerPart;
     KGraphViewer::KGraphViewerInterface* m_graphViewer;
@@ -209,6 +236,10 @@ private:
     KAction* m_shortenTemplates;
 
     ParseWorker* m_parseWorker;
+    bool m_isParseWorkerRunning;
+
+    QList<KUrl> m_filesToOpenList;
+    QList<bool> m_filesToOpenReloadList;
 };
 
 }
diff --git a/app/mainwindow.ui b/app/mainwindow.ui
index 8ac4119..7343319 100644
--- a/app/mainwindow.ui
+++ b/app/mainwindow.ui
@@ -12,7 +12,16 @@
   </property>
   <widget class="QWidget" name="centralwidget">
    <layout class="QVBoxLayout" name="verticalLayout_4">
-    <property name="margin">
+    <property name="leftMargin">
+     <number>0</number>
+    </property>
+    <property name="topMargin">
+     <number>0</number>
+    </property>
+    <property name="rightMargin">
+     <number>0</number>
+    </property>
+    <property name="bottomMargin">
      <number>0</number>
     </property>
     <item>
@@ -20,31 +29,7 @@
       <widget class="QWidget" name="displayPage">
        <layout class="QVBoxLayout" name="verticalLayout_6">
         <item>
-         <widget class="QTabWidget" name="tabWidget">
-          <property name="currentIndex">
-           <number>0</number>
-          </property>
-          <widget class="QWidget" name="plotterTab">
-           <attribute name="title">
-            <string>&amp;Evolution of Memory Consumption</string>
-           </attribute>
-           <layout class="QVBoxLayout" name="verticalLayout_2">
-            <property name="margin">
-             <number>0</number>
-            </property>
-           </layout>
-          </widget>
-          <widget class="QWidget" name="dotGraphTab">
-           <attribute name="title">
-            <string>&amp;Detailed Snapshot Analysis</string>
-           </attribute>
-           <layout class="QVBoxLayout" name="verticalLayout_3">
-            <property name="margin">
-             <number>0</number>
-            </property>
-           </layout>
-          </widget>
-         </widget>
+         <widget class="QTabWidget" name="filesTabWidget"/>
         </item>
        </layout>
       </widget>
@@ -170,7 +155,7 @@
      <x>0</x>
      <y>0</y>
      <width>800</width>
-     <height>22</height>
+     <height>19</height>
     </rect>
    </property>
   </widget>
