diff -r 325145377713 libgui/src/main-window.cc
--- a/libgui/src/main-window.cc	Wed Apr 11 10:38:08 2018 -0400
+++ b/libgui/src/main-window.cc	Thu Apr 12 13:49:06 2018 +0800
@@ -157,6 +157,7 @@
       m_doc_browser_window (nullptr), m_editor_window (nullptr),
       m_workspace_window (nullptr), m_variable_editor_window (nullptr),
       m_settings_dlg (nullptr), m_find_files_dlg (nullptr),
+      m_set_path_dlg (nullptr),
       m_release_notes_window (nullptr), m_community_news_window (nullptr),
       m_octave_qt_link (nullptr), m_clipboard (QApplication::clipboard ()),
       m_prevent_readline_conflicts (true), m_suppress_dbg_location (true),
@@ -275,6 +276,11 @@
         delete m_community_news_window;
         m_community_news_window = nullptr;
       }
+    if (m_set_path_dlg)
+      {
+        delete m_set_path_dlg;
+        m_set_path_dlg = nullptr;
+      }
   }
 
   bool main_window::command_window_has_focus (void) const
@@ -668,14 +674,14 @@
     }
 
     widget_icon_data[] =
-    {
-      // array of possible icon sets (name, path (complete for NONE))
-      // the first entry here is the default!
-      {"NONE",    ":/actions/icons/logo.png"},
-      {"GRAPHIC", ":/actions/icons/graphic_logo_"},
-      {"LETTER",  ":/actions/icons/letter_logo_"},
-      {"", ""} // end marker has empty name
-    };
+      {
+        // array of possible icon sets (name, path (complete for NONE))
+        // the first entry here is the default!
+        {"NONE",    ":/actions/icons/logo.png"},
+        {"GRAPHIC", ":/actions/icons/graphic_logo_"},
+        {"LETTER",  ":/actions/icons/letter_logo_"},
+        {"", ""} // end marker has empty name
+      };
 
     int count = 0;
     int icon_set_found = 0; // default
@@ -707,7 +713,7 @@
       }
     if (widget_icon_data[icon_set_found].name != "NONE")
       m_release_notes_icon = widget_icon_data[icon_set_found].path
-                             + "ReleaseWidget.png";
+        + "ReleaseWidget.png";
     else
       m_release_notes_icon = ":/actions/icons/logo.png";
 
@@ -984,7 +990,7 @@
 
     QSettings *settings = resource_manager::get_settings ();
     bool is_internal = m_editor_window
-                       && ! settings->value ("useCustomFileEditor",false).toBool ();
+                      && ! settings->value ("useCustomFileEditor",false).toBool ();
 
     // Create a NonModal message.
     QWidget *p = this;
@@ -1539,6 +1545,16 @@
     qApp->exit (exit_status);
   }
 
+  void main_window::handle_set_path_dialog_request (void)
+  {
+    if (m_set_path_dlg) return;
+    m_set_path_dlg = new set_path_dialog (this);
+
+    m_set_path_dlg->setModal (false);
+    m_set_path_dlg->setAttribute (Qt::WA_DeleteOnClose);
+    m_set_path_dlg->show ();
+  }
+
   void main_window::find_files (const QString& start_dir)
   {
 
@@ -1596,6 +1612,7 @@
         m_load_workspace_action->setShortcut (no_key);
         m_save_workspace_action->setShortcut (no_key);
         m_preferences_action->setShortcut (no_key);
+        m_set_path_action->setShortcut (no_key);
         m_exit_action->setShortcut (no_key);
 
         // edit menu
@@ -1999,7 +2016,7 @@
         connect (m_octave_qt_link,
                  SIGNAL (show_doc_signal (const QString &)),
                  this, SLOT (handle_show_doc (const QString &)));
-
+      
         connect (m_octave_qt_link,
                  SIGNAL (register_doc_signal (const QString &)),
                  this, SLOT (handle_register_doc (const QString &)));
@@ -2208,6 +2225,9 @@
 
     edit_menu->addSeparator ();
 
+    m_set_path_action
+      = edit_menu->addAction (tr ("Set Path"));
+
     m_preferences_action
       = edit_menu->addAction (resource_manager::icon ("preferences-system"),
                               tr ("Preferences..."));
@@ -2237,6 +2257,10 @@
 
     connect (m_preferences_action, SIGNAL (triggered (void)),
              this, SLOT (process_settings_dialog_request (void)));
+
+    connect (m_set_path_action, SIGNAL (triggered (void)),
+             this, SLOT (handle_set_path_dialog_request (void)));
+             
   }
 
   QAction * main_window::construct_debug_menu_item (const char *icon,
@@ -2609,6 +2633,7 @@
     shortcut_manager::set_shortcut (m_save_workspace_action,
                                     "main_file:save_workspace");
     shortcut_manager::set_shortcut (m_preferences_action, "main_file:preferences");
+    shortcut_manager::set_shortcut (m_set_path_action, "main_file:set_path");
     shortcut_manager::set_shortcut (m_exit_action,"main_file:exit");
 
     // edit menu
diff -r 325145377713 libgui/src/main-window.h
--- a/libgui/src/main-window.h	Wed Apr 11 10:38:08 2018 -0400
+++ b/libgui/src/main-window.h	Thu Apr 12 13:49:06 2018 +0800
@@ -48,6 +48,7 @@
 #include "documentation-dock-widget.h"
 #include "files-dock-widget.h"
 #include "find-files-dialog.h"
+#include "set-path-dialog.h"
 #include "history-dock-widget.h"
 #include "octave-cmd.h"
 #include "octave-dock-widget.h"
@@ -251,6 +252,8 @@
     void handle_octave_ready ();
     void handle_octave_finished (int);
 
+    void handle_set_path_dialog_request (void);
+
     //! Find files dialog.
     //!@{
     void find_files (const QString& startdir = QDir::currentPath ());
@@ -403,6 +406,7 @@
     QAction *m_new_figure_action;
     QAction *m_load_workspace_action;
     QAction *m_save_workspace_action;
+    QAction *m_set_path_action;
     QAction *m_preferences_action;
     QAction *m_exit_action;
 
@@ -459,6 +463,9 @@
 
     find_files_dialog *m_find_files_dlg;
 
+    //! Set path dialog
+    QPointer<set_path_dialog> m_set_path_dlg;
+
     //! Release notes window.
 
     QWidget *m_release_notes_window;
diff -r 325145377713 libgui/src/module.mk
--- a/libgui/src/module.mk	Wed Apr 11 10:38:08 2018 -0400
+++ b/libgui/src/module.mk	Thu Apr 12 13:49:06 2018 +0800
@@ -127,7 +127,9 @@
   %reldir%/moc-find-files-model.cc \
   %reldir%/qtinfo/moc-texinfo-parser.cc \
   %reldir%/qtinfo/moc-webinfo.cc \
-  %reldir%/moc-octave-dock-widget.cc
+  %reldir%/moc-octave-dock-widget.cc \
+  %reldir%/moc-set-path-dialog.cc \
+  %reldir%/moc-set-path-model.cc
 
 octave_gui_MOC += \
   $(OCTAVE_GUI_SRC_MOC) \
@@ -184,7 +186,10 @@
   %reldir%/workspace-model.h \
   %reldir%/workspace-view.h \
   %reldir%/variable-editor.h \
-  %reldir%/variable-editor-model.h
+  %reldir%/variable-editor-model.h \
+  %reldir%/set-path-dialog.h \
+  %reldir%/set-path-model.h
+
 
 %canon_reldir%_%canon_reldir%_la_SOURCES = \
   %reldir%/dialog.cc \
@@ -219,7 +224,9 @@
   %reldir%/workspace-model.cc \
   %reldir%/workspace-view.cc \
   %reldir%/variable-editor.cc \
-  %reldir%/variable-editor-model.cc
+  %reldir%/variable-editor-model.cc \
+  %reldir%/set-path-dialog.cc \
+  %reldir%/set-path-model.cc
 
 nodist_%canon_reldir%_%canon_reldir%_la_SOURCES = \
   $(octave_gui_MOC) \
diff -r 325145377713 libgui/src/set-path-dialog.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/set-path-dialog.cc	Thu Apr 12 13:49:06 2018 +0800
@@ -0,0 +1,189 @@
+/*
+
+Copyright (C) 
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <QPushButton>
+#include <QDialogButtonBox>
+#include <QGridLayout>
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QCheckBox>
+#include <QHeaderView>
+#include <QListView>
+#include <QFileDialog>
+#include <QStatusBar>
+#include <QIcon>
+#include <QFileInfo>
+#include <QTimer>
+#include <QDirIterator>
+#include <QTextStream>
+#include <QGroupBox>
+#include <QFileDialog>
+
+#include "set-path-dialog.h"
+#include "set-path-model.h"
+#include "resource-manager.h"
+
+namespace octave
+{
+  set_path_dialog::set_path_dialog (QWidget *parent)
+    : QDialog (parent)
+  {
+    setWindowTitle (tr ("Set Path"));
+
+    m_info_label = new QLabel (tr ("All changes take effect immediately."));
+
+    m_add_folder_button = new QPushButton (tr ("Add Folder..."));
+    m_move_to_top_button = new QPushButton (tr ("Move to Top"));
+    m_move_to_bottom_button = new QPushButton (tr ("Move to Bottom"));
+    m_move_up_button = new QPushButton (tr ("Move Up"));
+    m_move_down_button = new QPushButton (tr ("Move Down"));
+    m_remove_button = new QPushButton (tr ("Remove"));
+
+    m_save_button = new QPushButton (tr ("Save"));
+    m_revert_button = new QPushButton (tr ("Revert"));
+
+    m_save_button->setFocus();
+
+    connect (m_add_folder_button, SIGNAL (clicked (void)), this, SLOT (add_folder (void)));
+    connect (m_remove_button, SIGNAL (clicked (void)), this, SLOT (rmPath (void)));
+    connect (m_move_to_top_button, SIGNAL (clicked (void)), this, SLOT (moveToTopPath (void)));
+    connect (m_move_to_bottom_button, SIGNAL (clicked (void)), this, SLOT (moveToBottomPath (void)));
+    connect (m_move_up_button, SIGNAL (clicked (void)), this, SLOT (moveUpPath (void)));
+    connect (m_move_down_button, SIGNAL (clicked (void)), this, SLOT (moveDownPath (void)));
+
+    connect (m_save_button, SIGNAL (clicked (void)), this, SLOT (save (void)));
+    connect (m_revert_button, SIGNAL (clicked (void)), this, SLOT (revert (void)));
+
+    set_path_model *model = new set_path_model (this);
+
+    m_path_list = new QListView(this);
+    m_path_list->setWordWrap (false);
+    m_path_list->setModel (model);
+    m_path_list->setSelectionBehavior (QAbstractItemView::SelectRows);
+    m_path_list->setSelectionMode (QAbstractItemView::ExtendedSelection);
+    m_path_list->setAlternatingRowColors (true);
+
+    // layout everything
+    QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Horizontal);
+    button_box->addButton (m_save_button, QDialogButtonBox::ActionRole);
+
+    // add dialog close button
+    m_close_button = button_box->addButton (QDialogButtonBox::Close);
+    connect (button_box, SIGNAL (rejected (void)), this, SLOT (close (void)));
+
+    button_box->addButton (m_revert_button, QDialogButtonBox::ActionRole);
+
+    // path edit options
+    QDialogButtonBox *path_edit_layout = new QDialogButtonBox (Qt::Vertical);
+    path_edit_layout->addButton (m_add_folder_button, QDialogButtonBox::ActionRole);
+    path_edit_layout->addButton (m_move_to_top_button, QDialogButtonBox::ActionRole);
+    path_edit_layout->addButton (m_move_up_button, QDialogButtonBox::ActionRole);
+    path_edit_layout->addButton (m_move_down_button, QDialogButtonBox::ActionRole);
+    path_edit_layout->addButton (m_move_to_bottom_button, QDialogButtonBox::ActionRole);
+    path_edit_layout->addButton (m_remove_button, QDialogButtonBox::ActionRole);
+
+    // main layout
+    QHBoxLayout *main_hboxlayout = new QHBoxLayout;
+    main_hboxlayout->addWidget(path_edit_layout);
+    main_hboxlayout->addWidget(m_path_list);
+
+    QGridLayout *main_layout = new QGridLayout;
+    main_layout->addWidget (m_info_label, 0, 0);
+    main_layout->addLayout (main_hboxlayout, 1, 0);
+    main_layout->addWidget (button_box,2, 0);
+
+    setLayout (main_layout);
+  }
+
+  set_path_dialog::~set_path_dialog (void)
+  {
+  }
+
+  void set_path_dialog::add_folder(void)
+  {
+    QString dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"),
+                                                  "",
+                                                  QFileDialog::ShowDirsOnly
+                                                  | QFileDialog::DontResolveSymlinks);
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    m->addPath(dir);
+  }
+
+  void set_path_dialog::rmPath (void)
+  {
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    QItemSelectionModel *selmodel = m_path_list->selectionModel();
+    QModelIndexList indexlist = selmodel->selectedIndexes();
+    m->rmPath(indexlist);
+  }
+
+  void set_path_dialog::moveUpPath (void)
+  {
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    QItemSelectionModel *selmodel = m_path_list->selectionModel();
+    QModelIndexList indexlist = selmodel->selectedIndexes();
+    m->moveUpPath(indexlist);
+  }
+
+  void set_path_dialog::moveDownPath (void)
+  {
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    QItemSelectionModel *selmodel = m_path_list->selectionModel();
+    QModelIndexList indexlist = selmodel->selectedIndexes();
+    m->moveDownPath(indexlist);
+  }
+
+  void set_path_dialog::moveToTopPath (void)
+  {
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    QItemSelectionModel *selmodel = m_path_list->selectionModel();
+    QModelIndexList indexlist = selmodel->selectedIndexes();
+    m->moveToTopPath(indexlist);
+  }
+
+  void set_path_dialog::moveToBottomPath (void)
+  {
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    QItemSelectionModel *selmodel = m_path_list->selectionModel();
+    QModelIndexList indexlist = selmodel->selectedIndexes();
+    m->moveToBottomPath(indexlist);
+  }
+
+  void set_path_dialog::save (void)
+  {
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    m->save();
+  }
+
+  void set_path_dialog::revert (void)
+  {
+    set_path_model *m = static_cast<set_path_model *>(m_path_list->model());
+    m->revert();
+  }
+}
diff -r 325145377713 libgui/src/set-path-dialog.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/set-path-dialog.h	Thu Apr 12 13:49:06 2018 +0800
@@ -0,0 +1,83 @@
+/*
+
+Copyright (C)
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+#if ! defined (octave_set_path_dialog_h)
+#define octave_set_path_dialog_h 1
+
+#include <QDialog>
+#include <QModelIndex>
+#include <QFileInfo>
+
+class QLabel;
+class QPushButton;
+class QListView;
+class QVBoxLayout;
+class QHBoxLayout;
+
+namespace octave
+{
+  class set_path_dialog : public QDialog
+  {
+    Q_OBJECT
+
+  public:
+
+    set_path_dialog (QWidget *parent = nullptr);
+
+    virtual ~set_path_dialog (void);
+  signals:
+
+  public slots:
+
+  private slots:
+    void add_folder(void);
+
+    void rmPath (void);
+
+    void moveUpPath (void);
+
+    void moveDownPath (void);
+
+    void moveToTopPath (void);
+
+    void moveToBottomPath (void);
+
+    void save (void);
+
+    void revert (void);
+  private:
+    QLabel *m_info_label;
+    QPushButton *m_save_button;
+    QPushButton *m_close_button;
+    QPushButton *m_revert_button;
+
+    QListView *m_path_list;
+
+    QPushButton *m_add_folder_button;
+    QPushButton *m_move_to_top_button;
+    QPushButton *m_move_to_bottom_button;
+    QPushButton *m_move_up_button;
+    QPushButton *m_move_down_button;
+    QPushButton *m_remove_button;
+  };
+}
+
+#endif
diff -r 325145377713 libgui/src/set-path-model.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/set-path-model.cc	Thu Apr 12 13:49:06 2018 +0800
@@ -0,0 +1,321 @@
+/*
+
+Copyright (C)
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <string>
+#include <iostream>
+#include <algorithm>
+
+#include <QFileIconProvider>
+#include <QtAlgorithms>
+#include <QMessageBox>
+
+#include "parse.h"
+
+#include "set-path-model.h"
+
+namespace octave
+{
+    set_path_model::set_path_model (QObject *p)
+        :QAbstractListModel(p)
+    {
+        connect (this, SIGNAL (user_error_signal (const QString&, const QString&)),
+             this, SLOT (user_error (const QString&, const QString&)));
+        construct();
+    }
+
+    std::string set_path_model::to_string (void)
+    {
+        int parse_status = 0;
+        std::string path_str;
+
+        try
+        {
+            octave_value sep = eval_string ("pathsep", true, parse_status);
+            std::string path_sep = sep.string_value();
+
+            QStringList::iterator it = m_paths.begin();
+            while (it < m_paths.end())
+            {
+                if (it != m_paths.begin())
+                    path_str += path_sep;
+                path_str += it->toStdString();
+                ++it;
+            }
+        }
+        catch (execution_exception&)
+        {
+            evaluation_error ("pathsep");
+        }
+        return path_str;
+    }
+
+    void set_path_model::model_to_path (void)
+    {
+        int parse_status = 0;
+        QString path_str = QString::fromStdString (to_string());
+            std::string cmd = QString("path(\"%1\")").
+                arg(path_str).toStdString();
+        try
+        {
+            eval_string (cmd, true, parse_status);
+        }
+        catch (execution_exception&)
+        {
+            evaluation_error (cmd);
+        }
+    }
+
+    void set_path_model::clear (void)
+    {
+        beginResetModel ();
+
+        m_paths.clear ();
+
+        endResetModel ();
+    }
+
+    void set_path_model::save (void)
+    {
+        int parse_status = 0;
+        model_to_path();
+        try
+        {
+            eval_string ("savepath", true, parse_status);
+            m_old_paths = m_paths;
+        }
+        catch (execution_exception&)
+        {
+            evaluation_error ("savepath");
+        }
+    }
+
+    void set_path_model::revert (void)
+    {
+        clear();
+        beginInsertRows (QModelIndex (), 0, m_old_paths.size () - 1);
+        m_paths = m_old_paths;
+        endInsertRows ();
+        model_to_path();
+    }
+
+    void set_path_model::addPath (const QString& p)
+    {
+        beginInsertRows (QModelIndex (), m_paths.size (), m_paths.size ());
+
+        QList<QString>::Iterator it = m_paths.begin();
+
+        m_paths.insert (it, p);
+
+        endInsertRows ();
+
+        model_to_path();
+    }
+
+    void set_path_model::rmPath (const QModelIndexList& indices)
+    {
+        QModelIndexList sorted_indices(indices);
+        std::sort(sorted_indices.begin(), sorted_indices.end());
+        QStringList::iterator it = m_paths.begin();
+        int i = 0;
+        int index_top = 0;
+        while (it < m_paths.end())
+        {
+            if (index_top < sorted_indices.size() && i == sorted_indices[index_top].row())
+            {
+                int dis = std::distance(m_paths.begin(), it);
+                beginRemoveRows (QModelIndex (), dis, dis);
+                it = m_paths.erase(it);
+                endRemoveRows ();
+                ++index_top;
+            }
+            else
+            {
+                ++it;
+            }
+            ++i;
+        }
+        model_to_path();
+    }
+
+    void set_path_model::moveUpPath (const QModelIndexList& indices)
+    {
+        QModelIndexList sorted_indices(indices);
+        std::sort(sorted_indices.begin(), sorted_indices.end());
+        for (const auto&each : sorted_indices)
+        {
+            if (each.row() == 0) continue;
+            beginMoveRows (QModelIndex (), each.row(), each.row(),
+                QModelIndex (), each.row() - 1);
+            m_paths.swap(each.row() - 1, each.row());
+            endMoveRows ();
+        }
+        model_to_path();
+    }
+
+    void set_path_model::moveDownPath (const QModelIndexList& indices)
+    {
+        QModelIndexList sorted_indices(indices);
+        std::sort(sorted_indices.begin(), sorted_indices.end());
+        std::reverse(sorted_indices.begin(), sorted_indices.end());
+        for (const auto&each : sorted_indices)
+        {
+            if (each.row() == m_paths.size() - 1) continue;
+            beginMoveRows (QModelIndex (), each.row(), each.row(),
+                QModelIndex (), each.row() + 2);
+            m_paths.swap(each.row(), each.row() + 1);
+            endMoveRows ();
+        }
+        model_to_path();
+    }
+
+    void set_path_model::moveToTopPath (const QModelIndexList& indices)
+    {
+        QModelIndexList sorted_indices(indices);
+        std::sort(sorted_indices.begin(), sorted_indices.end());
+
+        QStringList::iterator it = m_paths.begin();
+        int i = 0;
+        int index_top = 0;
+        while (it < m_paths.end())
+        {
+            if (index_top < indices.size() && indices[index_top].row() == i)
+            {
+                int distance = std::distance(m_paths.begin(), it);
+                beginMoveRows (QModelIndex (), distance, distance,
+                    QModelIndex (), m_paths.size());
+                QString tmp = *it;
+                it = m_paths.erase(it);
+                m_paths.push_front(tmp);
+                endMoveRows ();
+                ++index_top;
+            }
+            else
+            {
+                ++it;
+            }
+            ++i;
+        }
+        std::reverse(m_paths.begin(), m_paths.begin() + indices.size());
+        model_to_path();
+    }
+
+    void set_path_model::moveToBottomPath (const QModelIndexList& indices)
+    {
+        QModelIndexList sorted_indices(indices);
+        std::sort(sorted_indices.begin(), sorted_indices.end());
+
+        QStringList::iterator it = m_paths.begin();
+        int i = 0;
+        int index_top = 0;
+        while (it < m_paths.end())
+        {
+            if (index_top < indices.size() && indices[index_top].row() == i)
+            {
+                int distance = std::distance(m_paths.begin(), it);
+                beginMoveRows (QModelIndex (), distance, distance,
+                    QModelIndex (), m_paths.size());
+                QString tmp = *it;
+                it = m_paths.erase(it);
+                m_paths.push_back(tmp);
+                endMoveRows ();
+                ++index_top;
+            }
+            else
+            {
+                ++it;
+            }
+            ++i;
+        }
+        model_to_path();
+    }
+
+    int set_path_model::rowCount (const QModelIndex&) const
+    {
+        return m_paths.size ();
+    }
+
+    QVariant set_path_model::data (const QModelIndex& idx, int role) const
+    {
+        QVariant retval;
+        if (idx.isValid ())
+        {
+            switch (role)  
+            {  
+            case Qt::DisplayRole:  
+                {  
+                    retval = QVariant(m_paths[idx.row()]); 
+                }
+                break;
+            case Qt::DecorationRole:
+                {  
+                    retval = QVariant(QIcon ());
+                }
+                break;
+            case Qt::SizeHintRole:
+                {
+                    retval = QVariant(QSize(10,20));
+                }
+            }
+        }
+        return retval;
+    }
+
+    void set_path_model::construct()
+    {
+        try
+        {
+            int parse_status = 0;
+
+            octave_value paths = eval_string ("path", true, parse_status);
+            octave_value sep = eval_string ("pathsep", true, parse_status);
+            QString qpaths = QString::fromStdString(paths.string_value());
+            m_paths = qpaths.split(sep.string_value().c_str());
+
+            // remove .
+            m_paths.removeAll(".");
+
+            m_old_paths = m_paths;
+        }
+        catch (execution_exception&)
+        {
+            evaluation_error ("path");
+        }
+    }
+
+    void
+    set_path_model::evaluation_error (const std::string& expr) const
+    {
+        emit user_error_signal ("Evaluation failed",
+                                QString ("failed to evaluate expression: '%1'")
+                                .arg (QString::fromStdString (expr)));
+    }
+
+    void
+    set_path_model::user_error (const QString& title, const QString& msg)
+    {
+        QMessageBox::critical (nullptr, title, msg);
+    }
+}
diff -r 325145377713 libgui/src/set-path-model.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/set-path-model.h	Thu Apr 12 13:49:06 2018 +0800
@@ -0,0 +1,83 @@
+/*
+
+Copyright (C)
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+#if ! defined (octave_set_path_model_h)
+#define octave_set_path_model_h 1
+
+#include <QAbstractListModel>
+#include <QStringList>
+#include <QList>
+#include <QFileInfo>
+#include <QIcon>
+
+namespace octave
+{
+  class set_path_model : public QAbstractListModel
+  {
+    Q_OBJECT
+
+  public:
+
+    set_path_model (QObject *p = nullptr);
+
+    ~set_path_model (void) = default;
+
+    void clear (void);
+
+    void save (void);
+
+    void revert (void);
+
+    void addPath (const QString& p);
+
+    void rmPath (const QModelIndexList& indices);
+
+    void moveUpPath (const QModelIndexList& indices);
+
+    void moveDownPath (const QModelIndexList& indices);
+
+    void moveToTopPath (const QModelIndexList& indices);
+
+    void moveToBottomPath (const QModelIndexList& indices);
+
+    std::string to_string (void);
+
+    void model_to_path (void);
+
+    int rowCount (const QModelIndex& p = QModelIndex ()) const;
+
+    QVariant data (const QModelIndex& idx, int role) const;
+
+  signals:
+    void user_error_signal (const QString& title, const QString& msg) const;
+
+  private slots:
+    void user_error (const QString& title, const QString& msg);
+
+  private:
+    void construct();
+    void evaluation_error (const std::string& expr) const;
+    QStringList m_paths;
+    QStringList m_old_paths;
+  };
+}
+
+#endif
