<commit_before>/******************************************************************************
**
** Copyright (C) 2009-2011 <NAME> <<EMAIL>>
**
** This file is part of chemkit. For more information see
** <http://www.chemkit.org>.
**
** chemkit is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** chemkit 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 chemkit. If not, see <http://www.gnu.org/licenses/>.
**
******************************************************************************/

#include "builderwindow.h"
#include "ui_builderwindow.h"

#include <algorithm>

#include <chemkit/bondpredictor.h>
#include <chemkit/graphicscamera.h>

#include "buildertool.h"
#include "navigatetool.h"
#include "buildtool.h"
#include "manipulatetool.h"
#include "energyminimizer.h"
#include "moleculelistdock.h"
#include "toolsettingsdock.h"
#include "displaysettingsdock.h"
#include "energyminimizationdock.h"
#include "moleculepropertiesdialog.h"

// --- Construction and Destruction ---------------------------------------- //
BuilderWindow::BuilderWindow(QWidget *parent)
    : QMainWindow(parent),
      ui(new Ui::BuilderWindow)
{
    // properties
    m_file = 0;
    m_molecule = 0;
    m_inMoleculeEdit = false;

    // setup ui
    ui->setupUi(this);
    connect(ui->actionOpen, SIGNAL(triggered()), SLOT(openFile()));
    connect(ui->actionSave, SIGNAL(triggered()), SLOT(saveFile()));
    connect(ui->actionSaveAs, SIGNAL(triggered()), SLOT(saveFileAs()));
    connect(ui->actionClose, SIGNAL(triggered()), SLOT(closeFile()));
    connect(ui->actionQuit, SIGNAL(triggered()), SLOT(quit()));
    connect(ui->actionAbout, SIGNAL(triggered()), SLOT(about()));
    connect(ui->actionUndo, SIGNAL(triggered()), SLOT(undo()));
    connect(ui->actionRedo, SIGNAL(triggered()), SLOT(redo()));
    connect(ui->actionCut, SIGNAL(triggered()), SLOT(cut()));
    connect(ui->actionCopy, SIGNAL(triggered()), SLOT(copy()));
    connect(ui->actionPaste, SIGNAL(triggered()), SLOT(paste()));
    connect(ui->actionDelete, SIGNAL(triggered()), SLOT(del()));
    connect(ui->actionCenterCamera, SIGNAL(triggered()), SLOT(centerCamera()));
    connect(ui->actionPredictBonds, SIGNAL(triggered()), SLOT(predictBonds()));
    connect(ui->actionAdjustHydrogens, SIGNAL(triggered()), SLOT(adjustHydrogens()));
    connect(ui->actionMoleculeProperties, SIGNAL(triggered()), SLOT(moleculeProperties()));

    QActionGroup *toolGroup = new QActionGroup(this);
    toolGroup->addAction(ui->actionNavigate);
    toolGroup->addAction(ui->actionBuild);
    toolGroup->addAction(ui->actionManipulate);
    toolGroup->setExclusive(true);
    connect(toolGroup, SIGNAL(triggered(QAction*)), SLOT(setTool(QAction*)));

    QActionGroup *backgroundColorGroup = new QActionGroup(this);
    backgroundColorGroup->addAction(ui->actionBackgroundBlack);
    backgroundColorGroup->addAction(ui->actionBackgroundWhite);
    backgroundColorGroup->addAction(ui->actionBackgroundGray);
    backgroundColorGroup->addAction(ui->actionBackgroundOther);
    backgroundColorGroup->setExclusive(true);
    connect(backgroundColorGroup, SIGNAL(triggered(QAction*)), SLOT(setBackgroundColor(QAction*)));

    // setup icons for menus and toolbars
    ui->actionOpen->setIcon(QIcon::fromTheme("document-open", style()->standardIcon(QStyle::SP_DialogOpenButton)));
    ui->actionSave->setIcon(QIcon::fromTheme("document-save", style()->standardIcon(QStyle::SP_DialogSaveButton)));
    ui->actionSaveAs->setIcon(QIcon::fromTheme("document-save-as"));
    ui->actionClose->setIcon(QIcon::fromTheme("window-close", style()->standardIcon(QStyle::SP_DirClosedIcon)));
    ui->actionQuit->setIcon(QIcon::fromTheme("application-exit", style()->standardIcon(QStyle::SP_DialogCloseButton)));
    ui->actionUndo->setIcon(QIcon::fromTheme("edit-undo", style()->standardIcon(QStyle::SP_ArrowBack)));
    ui->actionRedo->setIcon(QIcon::fromTheme("edit-redo", style()->standardIcon(QStyle::SP_ArrowForward)));
    ui->actionCut->setIcon(QIcon::fromTheme("edit-cut"));
    ui->actionCopy->setIcon(QIcon::fromTheme("edit-copy"));
    ui->actionPaste->setIcon(QIcon::fromTheme("edit-paste"));
    ui->actionDelete->setIcon(QIcon::fromTheme("edit-delete"));
    ui->actionAbout->setIcon(QIcon::fromTheme("help-about"));

    // setup view
    m_moleculeItem = 0;

    // setup molecule editor
    m_editor = new chemkit::MoleculeEditor;
    ui->actionUndo->setEnabled(false);
    ui->actionRedo->setEnabled(false);
    ui->actionCut->setEnabled(false);
    ui->actionCopy->setEnabled(false);
    ui->actionPaste->setEnabled(false);
    ui->actionDelete->setEnabled(false);
    connect(m_editor, SIGNAL(canUndoChanged(bool)), ui->actionUndo, SLOT(setEnabled(bool)));
    connect(m_editor, SIGNAL(canRedoChanged(bool)), ui->actionRedo, SLOT(setEnabled(bool)));
    connect(m_editor, SIGNAL(canPasteChanged(bool)), ui->actionPaste, SLOT(setEnabled(bool)));

    // setup energy minimizer
    m_energyMinimizer = new EnergyMinimizer;
    connect(m_energyMinimizer, SIGNAL(stateChanged(int)), SLOT(minimizerStateChanged(int)));

    // setup tools
    m_tool = 0;
    m_navigateTool = new NavigateTool(this);
    m_buildTool = new BuildTool(this);
    m_manipulateTool = new ManipulateTool(this);
    setTool(m_navigateTool);

    // dock widgets
    QDockWidget *dockWidget;

    // tool settings dock widget
    dockWidget = new ToolSettingsDock(this);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    // display settings dock widget
    dockWidget = new DisplaySettingsDock(this);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    // energy minimization dock widget
    dockWidget = new EnergyMinimizationDock(this);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    // molecule list dock widget
    dockWidget = new MoleculeListDock(this);
    addDockWidget(Qt::RightDockWidgetArea, dockWidget);
    dockWidget->setVisible(false);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    //setMolecule(0);
    setMolecule(new chemkit::Molecule);

    setTool(m_buildTool);
}

BuilderWindow::~BuilderWindow()
{
    ui->graphicsView->setTool(0);
    delete m_navigateTool;
    delete m_buildTool;
    delete m_manipulateTool;

//    delete m_editor;
//    delete m_molecule;
//    delete m_energyMinimizer;

    delete ui->graphicsView;
    delete ui;
}

void BuilderWindow::setTool(BuilderTool *tool)
{
    if(tool == m_tool){
        return; // no change
    }

    m_tool = tool;
    ui->graphicsView->setTool(tool);
    emit toolChanged(tool);

    if(tool == m_navigateTool)
        ui->actionNavigate->setChecked(true);
    else if(tool == m_buildTool)
        ui->actionBuild->setChecked(true);
    else if(tool == m_manipulateTool)
        ui->actionManipulate->setChecked(true);
}

void BuilderWindow::setMolecule(chemkit::Molecule *molecule)
{
    if(m_molecule == molecule){
        return;
    }

    // set molecule
    m_molecule = molecule;

    // remove old molecule item
    if(m_moleculeItem){
        ui->graphicsView->deleteItem(m_moleculeItem);
        m_moleculeItem = 0;
    }

    // add new molecule item
    if(molecule){
        m_moleculeItem = new chemkit::GraphicsMoleculeItem(molecule);
        ui->graphicsView->addItem(m_moleculeItem);
    }

    // reset editor
    m_editor->setMolecule(molecule);

    // reset energy minimizer
    m_energyMinimizer->setMolecule(molecule);

    centerCamera();

    // notify observers
    emit moleculeChanged(molecule);
}

chemkit::Molecule* BuilderWindow::molecule() const
{
    return m_molecule;
}

chemkit::GraphicsMoleculeItem* BuilderWindow::moleculeItem() const
{
    return m_moleculeItem;
}

chemkit::MoleculeEditor* BuilderWindow::editor() const
{
    return m_editor;
}

EnergyMinimizer* BuilderWindow::energyMinimizer() const
{
    return m_energyMinimizer;
}

void BuilderWindow::beginMoleculeEdit()
{
    m_editor->beginEdit();
    m_inMoleculeEdit = true;
}

void BuilderWindow::endMoleculeEdit()
{
    m_editor->endEdit();
    m_inMoleculeEdit = false;

    m_energyMinimizer->setMoleculeChanged(true);

    if(m_energyMinimizer->state() == EnergyMinimizer::Running ||
       m_energyMinimizer->state() == EnergyMinimizer::Converged ||
       m_energyMinimizer->state() == EnergyMinimizer::UpdateReady){
        m_energyMinimizer->start();
    }
}

// --- View ---------------------------------------------------------------- //
chemkit::GraphicsView* BuilderWindow::view() const
{
    return ui->graphicsView;
}

// --- Slots --------------------------------------------------------------- //
void BuilderWindow::openFile(const QString &fileName)
{
    // close current file
    closeFile();

    // open and read file
    chemkit::ChemicalFile *file = new chemkit::ChemicalFile(fileName.toStdString());
    if(!file->read()){
        QMessageBox::critical(this, "Error", QString("Error opening file: %1").arg(file->errorString().c_str()));
        delete file;
        return;
    }

    // set new file
    m_file = file;
    emit fileChanged(m_file);

    // set new molecule
    if(file->moleculeCount() > 0)
        setMolecule(file->molecule());

    if(!m_molecule || m_molecule->isEmpty()){
        setTool(m_buildTool);
    }
    else{
        setTool(m_navigateTool);
    }
}

void BuilderWindow::openFile()
{
    std::vector<std::string> formats = chemkit::ChemicalFile::formats();
    std::sort(formats.begin(), formats.end());

    QString formatsString;
    foreach(const QString &format, formatsString)
        formatsString += QString("*.%1 ").arg(format);

    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), 0, QString("Molecule Files (%1);;All Files (*.*)").arg(formatsString));

    if(!fileName.isEmpty()){
        openFile(fileName);
    }
}

void BuilderWindow::saveFile()
{
    if(!m_file || m_file->fileName().empty()){
        saveFileAs();
        return;
    }

    bool ok = m_file->write();

    if(!ok){
        QMessageBox::critical(this, "Error", QString("Error saving file: %1").arg(m_file->errorString().c_str()));
    }
}

void BuilderWindow::saveFileAs(const QString &fileName)
{
    if(!m_file){
        m_file = new chemkit::ChemicalFile(fileName.toStdString());
        m_file->addMolecule(m_molecule);
    }

    m_file->setFileName(fileName.toStdString());<commit_msg>Fix bug in BuilderWindow::openFile()<commit_after>/******************************************************************************
**
** Copyright (C) 2009-2011 <NAME> <<EMAIL>>
**
** This file is part of chemkit. For more information see
** <http://www.chemkit.org>.
**
** chemkit is free software: you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** chemkit 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 chemkit. If not, see <http://www.gnu.org/licenses/>.
**
******************************************************************************/

#include "builderwindow.h"
#include "ui_builderwindow.h"

#include <algorithm>

#include <chemkit/bondpredictor.h>
#include <chemkit/graphicscamera.h>

#include "buildertool.h"
#include "navigatetool.h"
#include "buildtool.h"
#include "manipulatetool.h"
#include "energyminimizer.h"
#include "moleculelistdock.h"
#include "toolsettingsdock.h"
#include "displaysettingsdock.h"
#include "energyminimizationdock.h"
#include "moleculepropertiesdialog.h"

// --- Construction and Destruction ---------------------------------------- //
BuilderWindow::BuilderWindow(QWidget *parent)
    : QMainWindow(parent),
      ui(new Ui::BuilderWindow)
{
    // properties
    m_file = 0;
    m_molecule = 0;
    m_inMoleculeEdit = false;

    // setup ui
    ui->setupUi(this);
    connect(ui->actionOpen, SIGNAL(triggered()), SLOT(openFile()));
    connect(ui->actionSave, SIGNAL(triggered()), SLOT(saveFile()));
    connect(ui->actionSaveAs, SIGNAL(triggered()), SLOT(saveFileAs()));
    connect(ui->actionClose, SIGNAL(triggered()), SLOT(closeFile()));
    connect(ui->actionQuit, SIGNAL(triggered()), SLOT(quit()));
    connect(ui->actionAbout, SIGNAL(triggered()), SLOT(about()));
    connect(ui->actionUndo, SIGNAL(triggered()), SLOT(undo()));
    connect(ui->actionRedo, SIGNAL(triggered()), SLOT(redo()));
    connect(ui->actionCut, SIGNAL(triggered()), SLOT(cut()));
    connect(ui->actionCopy, SIGNAL(triggered()), SLOT(copy()));
    connect(ui->actionPaste, SIGNAL(triggered()), SLOT(paste()));
    connect(ui->actionDelete, SIGNAL(triggered()), SLOT(del()));
    connect(ui->actionCenterCamera, SIGNAL(triggered()), SLOT(centerCamera()));
    connect(ui->actionPredictBonds, SIGNAL(triggered()), SLOT(predictBonds()));
    connect(ui->actionAdjustHydrogens, SIGNAL(triggered()), SLOT(adjustHydrogens()));
    connect(ui->actionMoleculeProperties, SIGNAL(triggered()), SLOT(moleculeProperties()));

    QActionGroup *toolGroup = new QActionGroup(this);
    toolGroup->addAction(ui->actionNavigate);
    toolGroup->addAction(ui->actionBuild);
    toolGroup->addAction(ui->actionManipulate);
    toolGroup->setExclusive(true);
    connect(toolGroup, SIGNAL(triggered(QAction*)), SLOT(setTool(QAction*)));

    QActionGroup *backgroundColorGroup = new QActionGroup(this);
    backgroundColorGroup->addAction(ui->actionBackgroundBlack);
    backgroundColorGroup->addAction(ui->actionBackgroundWhite);
    backgroundColorGroup->addAction(ui->actionBackgroundGray);
    backgroundColorGroup->addAction(ui->actionBackgroundOther);
    backgroundColorGroup->setExclusive(true);
    connect(backgroundColorGroup, SIGNAL(triggered(QAction*)), SLOT(setBackgroundColor(QAction*)));

    // setup icons for menus and toolbars
    ui->actionOpen->setIcon(QIcon::fromTheme("document-open", style()->standardIcon(QStyle::SP_DialogOpenButton)));
    ui->actionSave->setIcon(QIcon::fromTheme("document-save", style()->standardIcon(QStyle::SP_DialogSaveButton)));
    ui->actionSaveAs->setIcon(QIcon::fromTheme("document-save-as"));
    ui->actionClose->setIcon(QIcon::fromTheme("window-close", style()->standardIcon(QStyle::SP_DirClosedIcon)));
    ui->actionQuit->setIcon(QIcon::fromTheme("application-exit", style()->standardIcon(QStyle::SP_DialogCloseButton)));
    ui->actionUndo->setIcon(QIcon::fromTheme("edit-undo", style()->standardIcon(QStyle::SP_ArrowBack)));
    ui->actionRedo->setIcon(QIcon::fromTheme("edit-redo", style()->standardIcon(QStyle::SP_ArrowForward)));
    ui->actionCut->setIcon(QIcon::fromTheme("edit-cut"));
    ui->actionCopy->setIcon(QIcon::fromTheme("edit-copy"));
    ui->actionPaste->setIcon(QIcon::fromTheme("edit-paste"));
    ui->actionDelete->setIcon(QIcon::fromTheme("edit-delete"));
    ui->actionAbout->setIcon(QIcon::fromTheme("help-about"));

    // setup view
    m_moleculeItem = 0;

    // setup molecule editor
    m_editor = new chemkit::MoleculeEditor;
    ui->actionUndo->setEnabled(false);
    ui->actionRedo->setEnabled(false);
    ui->actionCut->setEnabled(false);
    ui->actionCopy->setEnabled(false);
    ui->actionPaste->setEnabled(false);
    ui->actionDelete->setEnabled(false);
    connect(m_editor, SIGNAL(canUndoChanged(bool)), ui->actionUndo, SLOT(setEnabled(bool)));
    connect(m_editor, SIGNAL(canRedoChanged(bool)), ui->actionRedo, SLOT(setEnabled(bool)));
    connect(m_editor, SIGNAL(canPasteChanged(bool)), ui->actionPaste, SLOT(setEnabled(bool)));

    // setup energy minimizer
    m_energyMinimizer = new EnergyMinimizer;
    connect(m_energyMinimizer, SIGNAL(stateChanged(int)), SLOT(minimizerStateChanged(int)));

    // setup tools
    m_tool = 0;
    m_navigateTool = new NavigateTool(this);
    m_buildTool = new BuildTool(this);
    m_manipulateTool = new ManipulateTool(this);
    setTool(m_navigateTool);

    // dock widgets
    QDockWidget *dockWidget;

    // tool settings dock widget
    dockWidget = new ToolSettingsDock(this);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    // display settings dock widget
    dockWidget = new DisplaySettingsDock(this);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    // energy minimization dock widget
    dockWidget = new EnergyMinimizationDock(this);
    addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    // molecule list dock widget
    dockWidget = new MoleculeListDock(this);
    addDockWidget(Qt::RightDockWidgetArea, dockWidget);
    dockWidget->setVisible(false);
    ui->menuView->addAction(dockWidget->toggleViewAction());

    //setMolecule(0);
    setMolecule(new chemkit::Molecule);

    setTool(m_buildTool);
}

BuilderWindow::~BuilderWindow()
{
    ui->graphicsView->setTool(0);
    delete m_navigateTool;
    delete m_buildTool;
    delete m_manipulateTool;

//    delete m_editor;
//    delete m_molecule;
//    delete m_energyMinimizer;

    delete ui->graphicsView;
    delete ui;
}

void BuilderWindow::setTool(BuilderTool *tool)
{
    if(tool == m_tool){
        return; // no change
    }

    m_tool = tool;
    ui->graphicsView->setTool(tool);
    emit toolChanged(tool);

    if(tool == m_navigateTool)
        ui->actionNavigate->setChecked(true);
    else if(tool == m_buildTool)
        ui->actionBuild->setChecked(true);
    else if(tool == m_manipulateTool)
        ui->actionManipulate->setChecked(true);
}

void BuilderWindow::setMolecule(chemkit::Molecule *molecule)
{
    if(m_molecule == molecule){
        return;
    }

    // set molecule
    m_molecule = molecule;

    // remove old molecule item
    if(m_moleculeItem){
        ui->graphicsView->deleteItem(m_moleculeItem);
        m_moleculeItem = 0;
    }

    // add new molecule item
    if(molecule){
        m_moleculeItem = new chemkit::GraphicsMoleculeItem(molecule);
        ui->graphicsView->addItem(m_moleculeItem);
    }

    // reset editor
    m_editor->setMolecule(molecule);

    // reset energy minimizer
    m_energyMinimizer->setMolecule(molecule);

    centerCamera();

    // notify observers
    emit moleculeChanged(molecule);
}

chemkit::Molecule* BuilderWindow::molecule() const
{
    return m_molecule;
}

chemkit::GraphicsMoleculeItem* BuilderWindow::moleculeItem() const
{
    return m_moleculeItem;
}

chemkit::MoleculeEditor* BuilderWindow::editor() const
{
    return m_editor;
}

EnergyMinimizer* BuilderWindow::energyMinimizer() const
{
    return m_energyMinimizer;
}

void BuilderWindow::beginMoleculeEdit()
{
    m_editor->beginEdit();
    m_inMoleculeEdit = true;
}

void BuilderWindow::endMoleculeEdit()
{
    m_editor->endEdit();
    m_inMoleculeEdit = false;

    m_energyMinimizer->setMoleculeChanged(true);

    if(m_energyMinimizer->state() == EnergyMinimizer::Running ||
       m_energyMinimizer->state() == EnergyMinimizer::Converged ||
       m_energyMinimizer->state() == EnergyMinimizer::UpdateReady){
        m_energyMinimizer->start();
    }
}

// --- View ---------------------------------------------------------------- //
chemkit::GraphicsView* BuilderWindow::view() const
{
    return ui->graphicsView;
}

// --- Slots --------------------------------------------------------------- //
void BuilderWindow::openFile(const QString &fileName)
{
    // close current file
    closeFile();

    // open and read file
    chemkit::ChemicalFile *file = new chemkit::ChemicalFile(fileName.toStdString());
    if(!file->read()){
        QMessageBox::critical(this, "Error", QString("Error opening file: %1").arg(file->errorString().c_str()));
        delete file;
        return;
    }

    // set new file
    m_file = file;
    emit fileChanged(m_file);

    // set new molecule
    if(file->moleculeCount() > 0)
        setMolecule(file->molecule());

    if(!m_molecule || m_molecule->isEmpty()){
        setTool(m_buildTool);
    }
    else{
        setTool(m_navigateTool);
    }
}

void BuilderWindow::openFile()
{
    std::vector<std::string> formats = chemkit::ChemicalFile::formats();
    std::sort(formats.begin(), formats.end());

    QString formatsString;
    foreach(const std::string &format, formats)
        formatsString += QString("*.%1 ").arg(format.c_str());

    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"), 0, QString("Molecule Files (%1);;All Files (*.*)").arg(formatsString));

    if(!fileName.isEmpty()){
        openFile(fileName);
    }
}

void BuilderWindow::saveFile()
{
    if(!m_file || m_file->fileName().empty()){
        saveFileAs();
        return;
    }

    bool ok = m_file->write();

    if(!ok){
        QMessageBox::critical(this, "Error", QString("Error saving file: %1").arg(m_file->errorString().c_str()));
    }
}

void BuilderWindow::saveFileAs(const QString &fileName)
{
    if(!m_file){
        m_file = new chemkit::ChemicalFile(fileName.toStdString());
        m_file->addMolecule(m_molecule);
    }

    m_file->setFileName(fileName.toStdString());
{'fraction_non_alphanumeric': 0.17418060810502803, 'fraction_numerical': 0.002005743720654602, 'mean_word_length': 4.234550226676211, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 275, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4804470', 'n_tokens_mistral': 6934, 'n_tokens_neox': 6613, 'n_words': 1170}