diff --git a/src/Model/Geometry/Profile.py b/src/Model/Geometry/Profile.py
index 59d677ea546badc88abd038ab768c300bb0db668..9583e42398f98f463f2e0cd3bf058594b1155b0a 100644
--- a/src/Model/Geometry/Profile.py
+++ b/src/Model/Geometry/Profile.py
@@ -1,5 +1,7 @@
 # -*- coding: utf-8 -*-
 
+from tools import timer
+
 from Model.Geometry.Point import Point
 from Model.Except import NotImplementedMethodeError
 
diff --git a/src/View/Geometry/GeometryWindow.py b/src/View/Geometry/GeometryWindow.py
index 180bfa0aa273a46b1a71014dce5df2ac10cf2c03..dbda85c22d02dffbf742a9f8c5005edf294befbf 100644
--- a/src/View/Geometry/GeometryWindow.py
+++ b/src/View/Geometry/GeometryWindow.py
@@ -352,14 +352,14 @@ class GeometryWindow(QMainWindow, WindowToolKit):
         self.select_current_profile()
         self.changed_slider_value()
 
-    def move_row_down(self):
+    def move_row_up(self):
         row = self.index_selected_row()
-        self._tablemodel.move_row_down(row)
+        self._tablemodel.move_row_up(row)
         self.select_current_profile()
 
-    def move_row_up(self):
+    def move_row_down(self):
         row = self.index_selected_row()
-        self._tablemodel.move_row_up(row)
+        self._tablemodel.move_row_down(row)
         self.select_current_profile()
 
     def copy(self):
diff --git a/src/View/Geometry/Profile/ProfileUndoCommand.py b/src/View/Geometry/Profile/ProfileUndoCommand.py
index 964a870bc7a4d1d0a711ea5b1ac11b0d0e64aafe..f63c11cc9ab1267ea7fb79de3396b0261f417051 100644
--- a/src/View/Geometry/Profile/ProfileUndoCommand.py
+++ b/src/View/Geometry/Profile/ProfileUndoCommand.py
@@ -83,7 +83,7 @@ class DelCommand(QUndoCommand):
             self._profile.delete(row)
 
 class SortCommand(QUndoCommand):
-    def __init__(self, profile, column _reverse):
+    def __init__(self, profile, column, _reverse):
         QUndoCommand.__init__(self)
 
         self._profile = profile
diff --git a/src/View/Geometry/Profile/ProfileWindow.py b/src/View/Geometry/Profile/ProfileWindow.py
index 4bb712333b766bb15612cbbadb1e02b2e52b8fdf..c9bfeee3d492bc3c5f7e8088dd5bfa01e38e6c79 100644
--- a/src/View/Geometry/Profile/ProfileWindow.py
+++ b/src/View/Geometry/Profile/ProfileWindow.py
@@ -5,6 +5,8 @@ import sys
 import csv
 from time import time
 
+from tools import trace, timer
+
 from PyQt5 import QtWidgets, QtGui
 from PyQt5.QtCore import QModelIndex, Qt, QEvent, QCoreApplication
 from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QCheckBox
@@ -37,7 +39,6 @@ class ProfileWindow(QMainWindow):
         self.graph()
 
         self._model.dataChanged.connect(self.graph)
-        self.filters = "CSV files (*.csv)"
         self.fileName = None
 
         self.ui.tableView.installEventFilter(self)
@@ -86,27 +87,30 @@ class ProfileWindow(QMainWindow):
         self.ui.btn_reset.clicked.connect(self.go_back_to_initial_state)
 
     def setup_model(self):
-        self._model = qtableview_profile.PandasModelEditable(self._profile)
+        self._model = PandasModelEditable(self._profile)
         self._last_saved_model_data = copy.deepcopy(self._model.model_data)
         self.__initial_model_data = copy.deepcopy(self._model.model_data)
 
         self.ui.tableView.setModel(self._model)
-        self.ui.tableView.setItemDelegate(qtableview_profile.Delegate())
+        self.ui.tableView.setItemDelegate(Delegate())
 
+    @timer
     def graph(self):
         """
         Returns: Le tracé de la cote z en fonction de l'abscisse (calculée).
         """
-        x = self._model.station  # abscisse en travers
-        y = self._model.z  # cote z
-        ld = self._model.name  # nom des points
-        x_carto = self._model.x  # x 'cartographique'
-        y_carto = self._model.y  # y 'cartographique'
-
-        if len(self._model.x) >= 3 and len(self._model.y) >= 3 and len(self._model.station) >= 3:
-
-            self.ui.canvas.axes.cla()
-            self.ui.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+        x = self._profile.get_station()
+        y = self._profile.z()
+        gl = self._profile.name()
+        x_carto = self._profile.x()
+        y_carto = self._profile.y()
+
+        self.ui.canvas.axes.cla()
+        self.ui.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
+
+        if (len(x_carto) >= 3 and
+            len(y_carto) >= 3 and
+            len(x) >= 3):
             self.profile_line2D, = self.ui.canvas.axes.plot(
                 x, y, color='r', lw=1.5, markersize=7, marker='+',
                 picker=30
@@ -114,8 +118,7 @@ class ProfileWindow(QMainWindow):
             self.ui.canvas.axes.set_xlabel(
                 _translate("MainWindowProfile",
                            "Abscisse en travers (m)"),
-                color='black',
-                fontsize=10
+                color='black', fontsize=10
             )
             self.ui.canvas.axes.set_ylabel(
                 _translate("MainWindowProfile", "Cote (m)"),
@@ -124,7 +127,7 @@ class ProfileWindow(QMainWindow):
 
             # Add label on graph
             self.annotation = []
-            for i, txt in enumerate(list(ld)):
+            for i, txt in enumerate(list(gl)):
                 annotation = self.ui.canvas.axes.annotate(
                     txt, (x[i], y[i]),
                     horizontalalignment='left',
@@ -136,11 +139,10 @@ class ProfileWindow(QMainWindow):
                 annotation.set_color("black")
                 self.annotation.append(annotation)
 
-            al = 8.  # arrow length in points
+            al = 8.
             arrowprops = dict(
-                clip_on=True,  # plotting outside axes on purpose
-                #    frac=1.,  # make end arrowhead the whole size of arrow
-                headwidth=5.,  # in points
+                clip_on=True,
+                headwidth=5.,
                 facecolor='k'
             )
             kwargs = dict(
@@ -150,120 +152,100 @@ class ProfileWindow(QMainWindow):
             )
 
             self.ui.canvas.axes.annotate("", (1, 0), xytext=(-al, 0), **kwargs)
-            self.ui.canvas.axes.annotate("", (0, 1), xytext=(0, -al), **kwargs)  # left spin arrow
+            self.ui.canvas.axes.annotate("", (0, 1), xytext=(0, -al), **kwargs)
 
             self.ui.canvas.axes.spines[['top', 'right']].set_color('none')
             self.ui.canvas.axes.yaxis.tick_left()
             self.ui.canvas.axes.xaxis.tick_bottom()
-            self.ui.canvas.axes.set_facecolor('#F9F9F9')  # '#E0FFFF')
+            self.ui.canvas.axes.set_facecolor('#F9F9F9')
             self.ui.canvas.figure.patch.set_facecolor('white')
 
             try:
-                self.onpick_event = OnpickEvent(self.ui.canvas.axes, x, y, x_carto, y_carto, self.ui.tableView)
-                self.ui.canvas.figure.canvas.mpl_connect('pick_event', self.onpick_event.onpick)
-
-                self.onclick_event = OnpickEvent(self.ui.canvas.axes, x, y, x_carto, y_carto, self.ui.tableView)
-                self.ui.canvas.figure.canvas.mpl_connect('button_press_event', self.onclick_event.onclick)
+                self.onpick_event = OnpickEvent(
+                    self.ui.canvas.axes,
+                    x, y, x_carto, y_carto,
+                    self.ui.tableView
+                )
+                self.ui.canvas\
+                       .figure\
+                       .canvas\
+                       .mpl_connect('pick_event', self.onpick_event.onpick)
+
+                self.onclick_event = OnpickEvent(
+                    self.ui.canvas.axes,
+                    x, y, x_carto, y_carto,
+                    self.ui.tableView
+                )
+                self.ui.canvas\
+                       .figure\
+                       .canvas\
+                       .mpl_connect('button_press_event', self.onclick_event.onclick)
             except:
                 print("TODO")
 
             self.ui.canvas.figure.tight_layout()
             self.ui.canvas.figure.canvas.draw_idle()
-        else:
-            self.ui.canvas.axes.cla()
-            self.ui.canvas.axes.grid(color='grey', linestyle='--', linewidth=0.5)
 
     def insert_row(self):
-        if len(self.ui.tableView.selectedIndexes()) == 0:
-            self._model.insertRows(self._model.rowCount(), 1)
+        if len(self.tableView.selectedIndexes()) == 0:
+            self._tablemodel.insert_row(self._tablemodel.rowCount())
         else:
-            rows = list(set([index.row() for index in self.ui.tableView.selectedIndexes()]))
-            for row in rows:  # [::-1]:
-                self._model.insertRows(row + 1, 1)
-
-        try:
-            self.graph()
-        except:
-            pass
-
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
+            row = self.index_selected_row()
+            self._tablemodel.insert_row(row + 1)
 
     def delete_row(self):
-        rows = list(set([index.row() for index in self.ui.tableView.selectedIndexes()]))
+        rows = sorted(
+            list(
+                set(
+                    [index.row() for index in self.tableView.selectedIndexes()]
+                )
+            )
+        )
 
         if len(rows) > 0:
-            self._model.remove_rows(rows)
-
-        try:
-            self.graph()
-        except:
-            print("TODO")
-
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
+            self._tablemodel.remove_rows(rows)
 
     def sort_X_ascending(self):
-        self._model.sort(0, order=Qt.AscendingOrder)
+        self._model.sort('x', order=Qt.AscendingOrder)
         self.graph()
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
 
     def sort_X_descending(self):
-        self._model.sort(0, order=Qt.DescendingOrder)
+        self._model.sort('x', order=Qt.DescendingOrder)
         self.graph()
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
 
     def sort_Y_ascending(self):
-        self._model.sort(1, order=Qt.AscendingOrder)
+        self._model.sort('y', order=Qt.AscendingOrder)
         self.graph()
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
 
     def sort_Y_descending(self):
-        self._model.sort(1, order=Qt.DescendingOrder)
+        self._model.sort('y', order=Qt.DescendingOrder)
         self.graph()
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
 
     def move_row_down(self):
-        rows = list(set([index.row() for index in self.ui.tableView.selectedIndexes()]))
+        rows = list(
+            set(
+                [index.row() for index in self.ui.tableView.selectedIndexes()]
+            )
+        )
 
         for row in rows:
             if row < self._model.rowCount() - 1:
                 self._model.moveRowDown(row)
 
         self.graph()
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
 
     def move_row_up(self):
-        rows = list(set([index.row() for index in self.ui.tableView.selectedIndexes()]))
+        rows = list(
+            set(
+                [index.row() for index in self.ui.tableView.selectedIndexes()]
+            )
+        )
 
         for row in rows:
             if 0 < row:
                 self._model.moveRowUp(row)
 
         self.graph()
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
 
     def eventFilter(self, source, event):
         if event.type() == QEvent.KeyPress:
@@ -302,9 +284,11 @@ class ProfileWindow(QMainWindow):
         print(minCol)
         print(minRow, columns)
         for index in selected:
-            self.clipboard.append((index.row() - minRow,
-                                   index.column() - minCol,
-                                   index.data_frame()))
+            self.clipboard.append(
+                (index.row() - minRow,
+                 index.column() - minCol,
+                 index.data_frame())
+            )
 
     def pasteSelection(self):
         if not self.clipboard:
@@ -358,15 +342,11 @@ class ProfileWindow(QMainWindow):
                     print("TODO")
 
         self.graph()
-        self.status_change_tableview = True
-        self.ui.btn_check.setEnabled(True)
-        self.ui.btn_go_back.setEnabled(True)
-        self.ui.btn_reset.setEnabled(True)
 
     def handleSave(self):
         if self.fileName is None or self.fileName == '':
             self.fileName, self.filters = QFileDialog.getSaveFileName(
-                self, filter=self.filters
+                self, filter="CSV files (*.csv)"
             )
 
         if self.fileName != '':
@@ -405,7 +385,7 @@ class ProfileWindow(QMainWindow):
                     buf.append(row)
 
                 self._model = None
-                self._model = qtableview_profile.PandasModelEditable(buf)
+                self._model = PandasModelEditable(buf)
                 self.ui.tableView.setModel(self._model)
                 self.fileName = ''
 
diff --git a/src/View/Geometry/Profile/qtableview_profile.py b/src/View/Geometry/Profile/qtableview_profile.py
index 6e237ac6ccc1f06a5369cff92d8830fd325f288b..7081ad48451c7a7276f240bb6f78275334b22ac2 100644
--- a/src/View/Geometry/Profile/qtableview_profile.py
+++ b/src/View/Geometry/Profile/qtableview_profile.py
@@ -111,7 +111,7 @@ class PandasModelEditable(QAbstractTableModel):
         if orientation == Qt.Horizontal and role == Qt.DisplayRole:
             return self._header[section]
         elif orientation == Qt.Vertical and role == Qt.DisplayRole:
-            return return str(section + 1)
+            return str(section + 1)
 
         if role == Qt.ToolTipRole and section == 4:
             return _translate(