Node_select.cpp 18 KB
Newer Older
Augustin Degomme's avatar
Augustin Degomme committed
1 2 3 4 5 6 7 8
/*
** This file is part of the ViTE project.
**
** This software is governed by the CeCILL-A license under French law
** and abiding by the rules of distribution of free software. You can
** use, modify and/or redistribute the software under the terms of the
** CeCILL-A license as circulated by CEA, CNRS and INRIA at the following
** URL: "http://www.cecill.info".
9
**
Augustin Degomme's avatar
Augustin Degomme committed
10 11 12 13 14
** As a counterpart to the access to the source code and rights to copy,
** modify and redistribute granted by the license, users are provided
** only with a limited warranty and the software's author, the holder of
** the economic rights, and the successive licensors have only limited
** liability.
15
**
Augustin Degomme's avatar
Augustin Degomme committed
16 17 18 19 20 21 22 23 24 25
** In this respect, the user's attention is drawn to the risks associated
** with loading, using, modifying and/or developing or reproducing the
** software by the user in light of its specific status of free software,
** that may mean that it is complicated to manipulate, and that also
** therefore means that it is reserved for developers and experienced
** professionals having in-depth computer knowledge. Users are therefore
** encouraged to load and test the software's suitability as regards
** their requirements in conditions enabling the security of their
** systems and/or data to be ensured and, more generally, to use and
** operate it in the same conditions as regards security.
26
**
Augustin Degomme's avatar
Augustin Degomme committed
27 28 29 30 31 32 33 34 35 36 37 38 39
** The fact that you are presently reading this means that you have had
** knowledge of the CeCILL-A license and that you accept its terms.
**
**
** ViTE developers are (for version 0.* to 1.0):
**
**        - COULOMB Kevin
**        - FAVERGE Mathieu
**        - JAZEIX Johnny
**        - LAGRASSE Olivier
**        - MARCOUEILLE Jule
**        - NOISETTE Pascal
**        - REDONDY Arthur
40
**        - VUCHENER Clément
Augustin Degomme's avatar
Augustin Degomme committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
**
*/
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>

/* -- */
#include "common/common.hpp"
#include "common/Info.hpp"
#include "common/Message.hpp"
#include "interface/resource.hpp"
#include "interface/Interface.hpp"

#include "core/Core.hpp"
#include "interface/Interface_graphic.hpp"
/* -- */
#include "trace/values/Values.hpp"
#include "trace/EntityValue.hpp"
#include "trace/EntityTypes.hpp"
#include "trace/Entitys.hpp"
#include "trace/tree/Interval.hpp"
#include "trace/Container.hpp"
/* -- */
#include <QFileDialog> // To choose the file to save
#include <QKeyEvent>
#include <QDropEvent>
#include <QtXml>
#include <QFile>
#include <iostream>

#include "interface/Node_select.hpp"
Q_DECLARE_METATYPE( Container * );

using namespace std;

82
Node_select::Node_select(Interface_graphic * console,QWidget *parent) : QWidget(parent), _trace(nullptr),_console(console), _sort_order(false) {
Augustin Degomme's avatar
Augustin Degomme committed
83 84 85 86
    setupUi(this);



87
    QMetaObject::connectSlotsByName(nullptr);
Augustin Degomme's avatar
Augustin Degomme committed
88 89
}

90
Node_select::~Node_select() = default;
Augustin Degomme's avatar
Augustin Degomme committed
91 92

void Node_select::set_initial_container_names(){
93

Augustin Degomme's avatar
Augustin Degomme committed
94 95 96 97 98 99
  const Container::Vector *root_containers = _trace->get_root_containers();

    if(root_containers->empty()) {
        *Message::get_instance() << tr("No containers in this trace").toStdString() << Message::ende;
        return;
    }
100
        _nodes_original->clear();
Augustin Degomme's avatar
Augustin Degomme committed
101 102 103 104 105 106
    // Add the root container names
    QList<QTreeWidgetItem *> items;
    QFlags<Qt::ItemFlag>     flg;
    for (Container::VectorIt it = root_containers->begin();
         it != root_containers->end();
         it ++) {
Mathieu Faverge's avatar
Mathieu Faverge committed
107
        string           name = (*it)->get_Name().to_string();
Augustin Degomme's avatar
Augustin Degomme committed
108
        QStringList      temp(QString::fromStdString(name));
109
        QTreeWidgetItem *current_node = new QTreeWidgetItem((QTreeWidgetItem *)nullptr, temp);
110
            current_node->setData(0,Qt::UserRole,qVariantFromValue(*it));//store the pointer to the container in the Data field
Augustin Degomme's avatar
Augustin Degomme committed
111
        items.append(current_node);
112

Augustin Degomme's avatar
Augustin Degomme committed
113
        // Recursivity to add the children names
114
        set_container_names_rec(current_node, (*it), flg, false);
Augustin Degomme's avatar
Augustin Degomme committed
115 116 117
    }

    _nodes_original->insertTopLevelItems(0, items);
118

Augustin Degomme's avatar
Augustin Degomme committed
119
    _nodes_original->expandAll();
120

Augustin Degomme's avatar
Augustin Degomme committed
121 122 123 124
}


void Node_select::set_displayed_container_names(){
125

126 127
    const Container::Vector *root_containers = _trace->get_view_root_containers();
    if(root_containers->empty())root_containers = _trace->get_root_containers();
128

Augustin Degomme's avatar
Augustin Degomme committed
129 130 131 132
    if(root_containers->empty()) {
        *Message::get_instance() << tr("No containers in this trace").toStdString() << Message::ende;
        return;
    }
133

134 135
    _displayed_containers.clear();
    _nodes_displayed->clear();
Augustin Degomme's avatar
Augustin Degomme committed
136 137 138 139 140 141
    // Add the root container names
    QList<QTreeWidgetItem *> items;
    QFlags<Qt::ItemFlag>     flg= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsTristate;
    for (Container::VectorIt it = root_containers->begin();
         it != root_containers->end();
         it ++) {
Mathieu Faverge's avatar
Mathieu Faverge committed
142
        string           name = (*it)->get_Name().to_string();
Augustin Degomme's avatar
Augustin Degomme committed
143
        QStringList      temp(QString::fromStdString(name));
144
        QTreeWidgetItem *current_node = new QTreeWidgetItem((QTreeWidgetItem *)nullptr, temp);
Augustin Degomme's avatar
Augustin Degomme committed
145

146
            current_node->setFlags(flg);
Augustin Degomme's avatar
Augustin Degomme committed
147 148 149
        current_node->setCheckState(0,Qt::Checked);
        current_node->setData(0,Qt::UserRole,qVariantFromValue(*it));//store the pointer to the container in the Data field
        items.append(current_node);
150

Augustin Degomme's avatar
Augustin Degomme committed
151
        // Recursivity to add the children names
152
        set_container_names_rec(current_node, (*it), flg, true);
Augustin Degomme's avatar
Augustin Degomme committed
153 154 155
    }

    _nodes_displayed->insertTopLevelItems(0, items);
156

Augustin Degomme's avatar
Augustin Degomme committed
157
    _nodes_displayed->expandAll();
158

Augustin Degomme's avatar
Augustin Degomme committed
159 160 161 162 163 164
}





165
void Node_select::set_container_names_rec(QTreeWidgetItem *current_node, Container *current_container, QFlags<Qt::ItemFlag> flg, bool load_view) {
166

167
    const Container::Vector *children;
168

169 170
    if(load_view==true)children = current_container->get_view_children();
    if(load_view==false || children->empty())children = current_container->get_children();
Augustin Degomme's avatar
Augustin Degomme committed
171 172 173 174 175 176
    //QFlags<Qt::ItemFlag>     flg= Qt::ItemIsDragEnabled;

    for (Container::VectorIt it = children->begin();
         it != children->end();
         it ++) {
        // We create the node and we do the recursivity
Mathieu Faverge's avatar
Mathieu Faverge committed
177
        string name = (*it)->get_Name().to_string();
Augustin Degomme's avatar
Augustin Degomme committed
178 179
        QStringList temp(QString::fromStdString(name));
        QTreeWidgetItem *node = new QTreeWidgetItem(current_node, temp);
180 181

            node->setFlags(flg);
Augustin Degomme's avatar
Augustin Degomme committed
182
        node->setData(0,Qt::UserRole, qVariantFromValue(*it));//store the pointer to the container in the Data field
183
                if(flg & Qt::ItemIsUserCheckable)node->setCheckState(0,Qt::Checked);
184
        set_container_names_rec(node ,(*it), flg, load_view);
Augustin Degomme's avatar
Augustin Degomme committed
185 186 187
    }
}

188
Trace* Node_select::get_trace() {
189
        return _trace;
190
}
Augustin Degomme's avatar
Augustin Degomme committed
191 192 193 194 195 196 197 198 199 200 201 202 203 204

void Node_select::set_trace(Trace *trace) {
    // Initialize _trace
    _trace = trace;
    // Fill the tree
    set_initial_container_names();
    set_displayed_container_names();
}
/*
void Stats_window::set_selected_nodes(string kind_of_state){
    const list<StateType *>          *states_types_list;
    list<StateType *>::const_iterator itstat;
    list<StateType *>::const_iterator endstat;
    const ContainerType              *kind_of_container = NULL;
205

Augustin Degomme's avatar
Augustin Degomme committed
206 207 208 209 210 211
    states_types_list = _trace->get_state_types();
    endstat = states_types_list->end();
    for (itstat  = states_types_list->begin();
         itstat != endstat;
         itstat++){
       if ((*itstat)->get_name().to_string() == kind_of_state){
212 213
         kind_of_container = (*itstat)->get_container_type();
         continue;
Augustin Degomme's avatar
Augustin Degomme committed
214 215 216 217 218 219 220 221 222 223 224 225 226
       }
    }

    // We delete the previous selected containers
    if(!_selected_containers.empty()) {
        _selected_containers.clear();
    }

    // We fill the new selected containers
    // TODO : Use the tree instead of the list
    QTreeWidgetItemIterator it(_nodes_selected);
    while (*it) {
        if ((*it)->checkState(0) == Qt::Checked){
227
            Container *cont = _trace->search_container((*it)->text(0).toStdString());
Augustin Degomme's avatar
Augustin Degomme committed
228
            //cout << ((ContainerType *)cont->get_type())->get_name().to_string() << " " << ((ContainerType *)kind_of_container)->get_name().to_string() << endl;
229 230
            if (cont->get_type() == kind_of_container)
              _selected_containers.push_back(cont);
Augustin Degomme's avatar
Augustin Degomme committed
231 232 233 234 235 236 237 238 239 240 241 242 243 244
        }
        it ++;
    }
    _number_of_selected_container = _selected_containers.size();

#ifdef STAT_DEBUG
    for(unsigned int i = 0 ; i < _selected_containers.size() ; i ++) {
        cout << _selected_containers[i]->get_name().to_string() << endl;
    }
#endif
}

*/

245 246
void Node_select::on_reset_button_clicked(){
    //resets to initial containers,
Augustin Degomme's avatar
Augustin Degomme committed
247
    _displayed_containers.clear();
248 249 250
    QList<QTreeWidgetItem *> items;
    QTreeWidgetItemIterator it(_nodes_original);//browse only top containers
    while (*it) {
251
        if((*it)->parent()==nullptr){//we only want parent nodes
252
            _displayed_containers.push_back(((*it)->data(0,Qt::UserRole)).value<Container*>());
253
            reassign_children_rec(*it,  nullptr);
Augustin Degomme's avatar
Augustin Degomme committed
254
        }
255
        ++it;
256

257
    }
258

259 260 261
    _nodes_displayed->clear();
    //can we load that from _nodes_original instead ?
    set_displayed_container_names();
262
    Element_pos zoom[2]={Info::Render::_x_min, Info::Render::_x_max};
263 264 265 266
    Info::Render::_x_min_visible = 0.0;
    Info::Render::_x_max_visible = 0.0;
    _trace->set_view_root_containers(_displayed_containers);
    //_trace->set_selected_container(_trace->get_root_containers());
Augustin Degomme's avatar
Augustin Degomme committed
267
    _console->get_console()->launch_action(Core:: _STATE_CLEAN_RENDER_AREA);
268 269 270
#if defined(USE_ITC) && defined(BOOST_SERIALIZE)
    _trace->updateTrace(new Interval(zoom[0], zoom[1]));
#endif
Augustin Degomme's avatar
Augustin Degomme committed
271
    _console->get_console()->draw_trace(_console->get_filename(),Core::_DRAW_OPENGL);
272
    _console->get_console()->launch_action(Core:: _STATE_ZOOM_IN_AN_INTERVAL, &zoom);
Augustin Degomme's avatar
Augustin Degomme committed
273
    _console->get_console()->launch_action(Core:: _STATE_RENDER_UPDATE);
274
}
Augustin Degomme's avatar
Augustin Degomme committed
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296



void Node_select::on_load_button_clicked(){
    //load an xml file and appply the structure described inside to the trace
     const QString path_by_default = QString(_file_viewed.substr(0, _file_viewed.find_last_of('.')).c_str()) + ".xml";

    QString filename = QFileDialog::getOpenFileName(this, tr("Import File"),
                                                    path_by_default,
                                                    tr("Documents XML (*.xml)"));

    if (filename.isEmpty()) {
        *Message::get_instance() << tr("No File Selected").toStdString() << Message::ende;
        return ;
    }
    else {
        // Adding .svg to the end
        if(!filename.endsWith(".xml")) {
            filename += ".xml";
        }
    }

297 298 299 300
        _trace->load_config_from_xml(filename); // we set the view_trace, but not our representation, we have to parse it again

        set_displayed_container_names();

Augustin Degomme's avatar
Augustin Degomme committed
301

302
}
Augustin Degomme's avatar
Augustin Degomme committed
303 304


305
void Node_select::on_display_button_clicked(){
Augustin Degomme's avatar
Augustin Degomme committed
306 307 308
    //take the new list and apply it to the trace
    // if not checked, remove container
    // if position has changed, set to the new position
309

Augustin Degomme's avatar
Augustin Degomme committed
310
    //we need to be recursive again, and to avoid problems with similar names
311 312 313 314 315 316


        /*
        //this only works to select containers, we cannot order them by this way
        _displayed_containers.clear();
         QTreeWidgetItemIterator it(_nodes_displayed, QTreeWidgetItemIterator::Checked);
Augustin Degomme's avatar
Augustin Degomme committed
317 318 319 320
     while (*it) {
         _displayed_containers.push_back(((*it)->data(0,Qt::UserRole)).value<Container*>());
         ++it;
     }
321 322
    _trace->set_selected_container(&_displayed_containers);*/

323
        //use _view_root containers and _view_children in order not to modify the actual structure and limit modifications to do in drawtrace
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
    _displayed_containers.clear();
    build_displayed_nodes(_displayed_containers);
    _trace->set_view_root_containers(_displayed_containers);
    Element_pos it[2]={Info::Render::_x_min, Info::Render::_x_max};
    //Info::Render::_x_min_visible = 0.0;
    //Info::Render::_x_max_visible = 0.0;
    _console->get_console()->launch_action(Core:: _STATE_CLEAN_RENDER_AREA);
    #if defined(USE_ITC) && defined(BOOST_SERIALIZE)
    _trace->updateTrace(new Interval(it[0], it[1]));
    #endif
    _console->get_console()->draw_trace(_console->get_filename(),Core::_DRAW_OPENGL);

    _console->get_console()->launch_action(Core:: _STATE_ZOOM_IN_AN_INTERVAL, &it);
    _console->get_console()->launch_action(Core:: _STATE_RENDER_UPDATE);
}
339 340


341 342 343
void Node_select::build_displayed_nodes( std::list<Container *>& displayed_containers){
    QTreeWidgetItemIterator it(_nodes_displayed, QTreeWidgetItemIterator::Checked);//browse only top containers
    while (*it) {
344
        if((*it)->parent()==nullptr){//we only want parent nodes
345 346 347
            displayed_containers.push_back(((*it)->data(0,Qt::UserRole)).value<Container*>());
            QFlags<Qt::CheckState> flg(Qt::Checked|Qt::PartiallyChecked);
            reassign_children_rec(*it,flg);
Augustin Degomme's avatar
Augustin Degomme committed
348
        }
349
        ++it;
Augustin Degomme's avatar
Augustin Degomme committed
350
     }
351
}
Augustin Degomme's avatar
Augustin Degomme committed
352 353


354
void Node_select::reassign_children_rec(QTreeWidgetItem* item,  QFlags<Qt::CheckState> flg){
Augustin Degomme's avatar
Augustin Degomme committed
355
    //browse all childs of a container, add him and recursively all its children to the view we want
356 357 358 359 360 361
    item->data(0,Qt::UserRole).value<Container*>()->clear_view_children();
    for(int i=0; i<item->childCount(); i++){
         if(flg==0 || (item->child(i)->checkState(0)& flg) ){
            item->data(0,Qt::UserRole).value<Container*>()->add_view_child(item->child(i)->data(0,Qt::UserRole).value<Container*>());
            reassign_children_rec(item->child(i), flg);
        }
362

363
    }
364

365
}
366 367


Augustin Degomme's avatar
Augustin Degomme committed
368 369 370 371 372 373 374
void Node_select::set_filename(string filename){
    _file_viewed = filename;
}


void Node_select::on_export_button_clicked(){
 //export the trees to a XML file, in order to allow easy reusing
375

Augustin Degomme's avatar
Augustin Degomme committed
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
    const QString path_by_default = QString(_file_viewed.substr(0, _file_viewed.find_last_of('.')).c_str()) + ".xml";

    QString filename = QFileDialog::getSaveFileName(this, tr("Export File"),
                                                    path_by_default,
                                                    tr("Documents XML (*.xml)"));

    if (filename.isEmpty()) {
        *Message::get_instance() << tr("You must select a name for the file").toStdString() << Message::ende;
        return ;
    }
    else {
        // Adding .svg to the end
        if(!filename.endsWith(".xml")) {
            filename += ".xml";
        }
    }
392

Augustin Degomme's avatar
Augustin Degomme committed
393 394 395
    QDomDocument doc( "Subset " );
    QDomElement root = doc.createElement( "nodes" );
    doc.appendChild( root );
396

Augustin Degomme's avatar
Augustin Degomme committed
397
    //go through all elements of _nodes_displayed
398 399
         QTreeWidgetItemIterator it(_nodes_displayed);//browse only top containers

Augustin Degomme's avatar
Augustin Degomme committed
400
     while (*it) {
401
        if((*it)->parent()==nullptr){//we only want parent nodes
Augustin Degomme's avatar
Augustin Degomme committed
402 403

            QDomElement rootElement = doc.createElement( "rootNode" );
Mathieu Faverge's avatar
Mathieu Faverge committed
404
            rootElement.setAttribute( "name", QString((*it)->data(0,Qt::UserRole).value<Container*>()->get_Name().to_string().c_str()) );
Augustin Degomme's avatar
Augustin Degomme committed
405 406 407 408 409

            export_children_rec(*it, rootElement, doc);
            root.appendChild( rootElement );
        }
        ++it;
410

Augustin Degomme's avatar
Augustin Degomme committed
411
     }
412

Augustin Degomme's avatar
Augustin Degomme committed
413 414 415 416 417
    QFile file( filename );
    if( !file.open( QIODevice::WriteOnly) ){
                *Message::get_instance() << tr("Error while opening the file").toStdString() << Message::ende;
                return ;
        }
418

Augustin Degomme's avatar
Augustin Degomme committed
419 420 421 422
    QTextStream ts( &file );
    ts << doc.toString();

    file.close();
423 424 425



Augustin Degomme's avatar
Augustin Degomme committed
426 427 428 429 430


}


431 432 433 434 435 436 437 438 439 440 441 442 443
void Node_select::on_sort_button_clicked(){
    //sort_order : 0 for high to low, 1 for low to high
    _sort_order=!_sort_order;
    sort_button->setText(_sort_order?"Sort >":"Sort <");
    _nodes_displayed->sortItems(0,_sort_order?Qt::AscendingOrder:Qt::DescendingOrder);

}


void Node_select::export_children_rec(QTreeWidgetItem* item, QDomElement& parent, QDomDocument& doc){
    for(int i=0; i<item->childCount(); i++){
        if((item->child(i)->checkState(0)& (Qt::Checked|Qt::PartiallyChecked)) ){
            QDomElement element = doc.createElement( "Node" );
Mathieu Faverge's avatar
Mathieu Faverge committed
444
            element.setAttribute( "name", QString(item->child(i)->data(0,Qt::UserRole).value<Container*>()->get_Name().to_string().c_str()) );
445 446
            parent.appendChild( element );
            export_children_rec(item->child(i), element, doc);
447

448
        }
449

450
    }
451

452
}
453

Augustin Degomme's avatar
Augustin Degomme committed
454 455 456 457 458 459 460 461

void Node_select::close_window(){
    hide();
}




462
void Node_select::keyPressEvent(QKeyEvent *) {
Augustin Degomme's avatar
Augustin Degomme committed
463 464 465 466 467 468 469
  /*  switch (event->key()) {
    case Qt::Key_Left:
        // Key 'left' pressed.
        if(_x_translated > 0) {
            _ui_stats_area->translate_x(--_x_translated);
            x_scroll->setSliderPosition(_x_translated);
        }
470
        break;
Augustin Degomme's avatar
Augustin Degomme committed
471 472 473 474 475 476
    case Qt::Key_Right:
        // Key 'right' pressed.
        if(_x_translated < 99) {
            _ui_stats_area->translate_x(++_x_translated);
            x_scroll->setSliderPosition(_x_translated);
        }
477
        break;
Augustin Degomme's avatar
Augustin Degomme committed
478
    case Qt::Key_Up:
479
        // Key 'up' pressed.
Augustin Degomme's avatar
Augustin Degomme committed
480 481 482 483
        if(_y_translated > 0) {
            _ui_stats_area->translate_y(--_y_translated);
            y_scroll->setSliderPosition(_y_translated);
        }
484
        break;
Augustin Degomme's avatar
Augustin Degomme committed
485
    case Qt::Key_Down:
486
        // Key 'down' pressed.
Augustin Degomme's avatar
Augustin Degomme committed
487 488 489 490
        if(_y_translated < 99) {
            _ui_stats_area->translate_y(++_y_translated);
             y_scroll->setSliderPosition(_y_translated);
       }
491
        break;
Augustin Degomme's avatar
Augustin Degomme committed
492
    case Qt::Key_PageUp:
493
        // Key 'Page Up' pressed.
Augustin Degomme's avatar
Augustin Degomme committed
494 495 496 497
        _ui_stats_area->translate_y(0);
        y_scroll->setSliderPosition(0);
        break;
    case Qt::Key_PageDown:
498
        // Key 'Page Down' pressed.
Augustin Degomme's avatar
Augustin Degomme committed
499 500 501 502 503
        _ui_stats_area->translate_y(100);
        y_scroll->setSliderPosition(100);
        break;
    default:

504
        break;
Augustin Degomme's avatar
Augustin Degomme committed
505
    }
506

Augustin Degomme's avatar
Augustin Degomme committed
507 508 509 510 511 512 513
    event->accept();*/
}
/*
void Stats_window::init() {
    // We set the names of the containers for the tree widget
    _nodes_selected->clear();
    set_container_names();
514

Augustin Degomme's avatar
Augustin Degomme committed
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
    // We init the times
    _start_time = Info::Render::_x_min_visible;
    _end_time   = Info::Render::_x_max_visible;

    QString temp;
    temp.setNum(_start_time);
    _start_time_widget->setText(temp);
    temp.setNum(_end_time);
    _end_time_widget->setText(temp);

    _ui_stats_area->clear();
    Reinit_scroll_bars();
}

void Stats_window::clear() {
    _ui_stats_area->makeCurrent();
    _nodes_selected->clear();
    _ui_stats_area->clear();
    _kind_of_state_box->clear();
    Reinit_scroll_bars();
    _ui_stats_area->doneCurrent();
}

void Stats_window::set_arguments(std::map<std::string , QVariant *>) {
}

void Stats_window::execute() {
542
       on_reload_button_clicked();
Augustin Degomme's avatar
Augustin Degomme committed
543 544 545 546 547
}

string Stats_window::get_name() {
    return "Statistics window";
}*/