view libgui/src/shortcuts-tree-widget.cc @ 31771:21f9b34eb893

maint: Eliminate "(void)" in C++ function prototypes/declarations. * mk-opts.pl, external.txi, embedded.cc, make_int.cc, standalone.cc, standalonebuiltin.cc, BaseControl.cc, BaseControl.h, ButtonControl.cc, ButtonControl.h, ButtonGroup.cc, ButtonGroup.h, Canvas.cc, Canvas.h, CheckBoxControl.cc, CheckBoxControl.h, Container.cc, Container.h, ContextMenu.cc, ContextMenu.h, EditControl.cc, EditControl.h, Figure.cc, Figure.h, FigureWindow.cc, FigureWindow.h, GLCanvas.cc, GLCanvas.h, GenericEventNotify.h, KeyMap.cc, ListBoxControl.cc, ListBoxControl.h, Logger.cc, Logger.h, Menu.cc, Menu.h, MenuContainer.h, Object.cc, Object.h, ObjectProxy.cc, ObjectProxy.h, Panel.cc, Panel.h, PopupMenuControl.cc, PopupMenuControl.h, PushButtonControl.cc, PushButtonControl.h, PushTool.cc, PushTool.h, RadioButtonControl.cc, RadioButtonControl.h, SliderControl.cc, SliderControl.h, Table.cc, Table.h, TextControl.cc, TextControl.h, TextEdit.h, ToggleButtonControl.cc, ToggleButtonControl.h, ToggleTool.cc, ToggleTool.h, ToolBar.cc, ToolBar.h, ToolBarButton.cc, ToolBarButton.h, gl-select.cc, gl-select.h, qopengl-functions.h, qt-graphics-toolkit.h, qdialog.cpp, qfontdialog.cpp, qprintdialog_win.cpp, liboctgui-build-info.h, liboctgui-build-info.in.cc, color-picker.cc, color-picker.h, command-widget.cc, command-widget.h, community-news.cc, community-news.h, dialog.cc, dialog.h, documentation-bookmarks.cc, documentation-bookmarks.h, documentation-dock-widget.cc, documentation-dock-widget.h, documentation.cc, documentation.h, dw-main-window.cc, dw-main-window.h, external-editor-interface.cc, external-editor-interface.h, files-dock-widget.cc, files-dock-widget.h, find-files-dialog.cc, find-files-dialog.h, find-files-model.cc, find-files-model.h, gui-preferences.cc, gui-preferences.h, gui-settings.cc, gui-settings.h, history-dock-widget.cc, history-dock-widget.h, interpreter-qobject.cc, interpreter-qobject.h, file-editor-interface.h, file-editor-tab.cc, file-editor-tab.h, file-editor.cc, file-editor.h, find-dialog.cc, find-dialog.h, marker.cc, marker.h, octave-qscintilla.cc, octave-qscintilla.h, octave-txt-lexer.cc, octave-txt-lexer.h, main-window.cc, main-window.h, news-reader.cc, news-reader.h, octave-dock-widget.cc, octave-dock-widget.h, octave-qobject.cc, octave-qobject.h, qt-application.cc, qt-application.h, qt-interpreter-events.cc, qt-interpreter-events.h, release-notes.cc, release-notes.h, set-path-dialog.cc, set-path-dialog.h, set-path-model.cc, set-path-model.h, settings-dialog.cc, settings-dialog.h, shortcuts-tree-widget.cc, shortcuts-tree-widget.h, tab-bar.cc, tab-bar.h, terminal-dock-widget.cc, terminal-dock-widget.h, variable-editor-model.cc, variable-editor-model.h, variable-editor.cc, variable-editor.h, welcome-wizard.cc, welcome-wizard.h, workspace-model.cc, workspace-model.h, workspace-view.cc, workspace-view.h, build-env.h, Cell.cc, Cell.h, __contourc__.cc, __magick_read__.cc, auto-shlib.cc, auto-shlib.h, base-text-renderer.h, bsxfun.cc, c-file-ptr-stream.cc, c-file-ptr-stream.h, call-stack.cc, call-stack.h, debug.cc, defaults.cc, defaults.h, defun.cc, display.cc, display.h, dynamic-ld.cc, dynamic-ld.h, environment.cc, environment.h, error.cc, error.h, errwarn.cc, errwarn.h, event-manager.cc, event-manager.h, event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, ft-text-renderer.cc, ft-text-renderer.h, genprops.awk, gh-manager.cc, gh-manager.h, gl-render.cc, gl-render.h, gl2ps-print.cc, graphics-toolkit.h, graphics.cc, graphics.in.h, gtk-manager.cc, gtk-manager.h, help.cc, help.h, hook-fcn.h, input.cc, input.h, interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h, jsondecode.cc, latex-text-renderer.cc, latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h, ls-hdf5.cc, ls-hdf5.h, mxarray.h, oct-errno.h, oct-errno.in.cc, oct-fstrm.cc, oct-fstrm.h, oct-handle.h, oct-hist.cc, oct-hist.h, oct-iostrm.cc, oct-iostrm.h, oct-map.cc, oct-map.h, oct-opengl.h, oct-prcstrm.cc, oct-prcstrm.h, oct-procbuf.cc, oct-procbuf.h, oct-process.h, oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.cc, oct-strstrm.h, oct-tex-lexer.in.ll, pager.cc, pager.h, pr-flt-fmt.cc, pr-flt-fmt.h, pr-output.cc, pr-output.h, procstream.cc, procstream.h, settings.cc, settings.h, sighandlers.cc, sighandlers.h, stack-frame.cc, stack-frame.h, svd.cc, syminfo.cc, syminfo.h, symrec.cc, symrec.h, symscope.cc, symscope.h, symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h, text-renderer.cc, text-renderer.h, toplev.cc, url-handle-manager.cc, url-handle-manager.h, variables.cc, xpow.cc, __init_fltk__.cc, __init_gnuplot__.cc, __ode15__.cc, audiodevinfo.cc, gzip.cc, liboctinterp-build-info.h, liboctinterp-build-info.in.cc, mk-build-env-features.sh, mk-builtins.pl, cdef-class.cc, cdef-class.h, cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h, cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h, cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-diag.h, ov-base-int.cc, ov-base-int.h, ov-base-mat.cc, ov-base-mat.h, ov-base-scalar.cc, ov-base-scalar.h, ov-base-sparse.cc, ov-base-sparse.h, ov-base.cc, ov-base.h, ov-bool-mat.cc, ov-bool-mat.h, ov-bool-sparse.cc, ov-bool-sparse.h, ov-bool.cc, ov-bool.h, ov-builtin.cc, ov-builtin.h, ov-cell.cc, ov-cell.h, ov-ch-mat.cc, ov-ch-mat.h, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h, ov-colon.h, ov-complex.cc, ov-complex.h, ov-cs-list.h, ov-cx-diag.cc, ov-cx-diag.h, ov-cx-mat.cc, ov-cx-mat.h, ov-cx-sparse.cc, ov-cx-sparse.h, ov-dld-fcn.cc, ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.cc, ov-fcn.h, ov-float.cc, ov-float.h, ov-flt-complex.cc, ov-flt-complex.h, ov-flt-cx-diag.cc, ov-flt-cx-diag.h, ov-flt-cx-mat.cc, ov-flt-cx-mat.h, ov-flt-re-diag.cc, ov-flt-re-diag.h, ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-java.h, ov-lazy-idx.cc, ov-lazy-idx.h, ov-legacy-range.cc, ov-legacy-range.h, ov-magic-int.cc, ov-magic-int.h, ov-mex-fcn.cc, ov-mex-fcn.h, ov-null-mat.cc, ov-null-mat.h, ov-oncleanup.cc, ov-oncleanup.h, ov-perm.cc, ov-perm.h, ov-range.cc, ov-range.h, ov-re-diag.cc, ov-re-diag.h, ov-re-mat.cc, ov-re-mat.h, ov-re-sparse.cc, ov-re-sparse.h, ov-scalar.cc, ov-scalar.h, ov-str-mat.cc, ov-str-mat.h, ov-struct.cc, ov-struct.h, ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.cc, ovl.h, octave.cc, octave.h, anon-fcn-validator.h, bp-table.cc, bp-table.h, comment-list.cc, comment-list.h, filepos.h, lex.h, lex.ll, oct-lvalue.cc, oct-lvalue.h, oct-parse.yy, parse.h, profiler.cc, profiler.h, pt-anon-scopes.h, pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h, pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc, pt-binop.h, pt-bp.h, pt-cbinop.h, pt-cell.h, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h, pt-colon.h, pt-const.h, pt-decl.cc, pt-decl.h, pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h, pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h, pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.h, pt-misc.cc, pt-misc.h, pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h, pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h, pt-walk.h, pt.cc, pt.h, token.cc, token.h, usage.h, Array-base.cc, Array.h, CColVector.cc, CColVector.h, CDiagMatrix.cc, CDiagMatrix.h, CMatrix.cc, CMatrix.h, CNDArray.cc, CNDArray.h, CRowVector.cc, CRowVector.h, CSparse.cc, CSparse.h, DiagArray2.cc, DiagArray2.h, MArray.cc, MArray.h, MDiagArray2.h, MSparse.h, MatrixType.cc, MatrixType.h, PermMatrix.cc, PermMatrix.h, Range.cc, Range.h, Sparse-b.cc, Sparse.cc, Sparse.h, boolMatrix.cc, boolMatrix.h, boolNDArray.cc, boolNDArray.h, boolSparse.cc, boolSparse.h, chMatrix.h, chNDArray.h, dColVector.cc, dColVector.h, dDiagMatrix.cc, dDiagMatrix.h, dMatrix.cc, dMatrix.h, dNDArray.cc, dNDArray.h, dRowVector.cc, dRowVector.h, dSparse.cc, dSparse.h, dim-vector.cc, dim-vector.h, fCColVector.cc, fCColVector.h, fCDiagMatrix.cc, fCDiagMatrix.h, fCMatrix.cc, fCMatrix.h, fCNDArray.cc, fCNDArray.h, fCRowVector.cc, fCRowVector.h, fColVector.cc, fColVector.h, fDiagMatrix.cc, fDiagMatrix.h, fMatrix.cc, fMatrix.h, fNDArray.cc, fNDArray.h, fRowVector.cc, fRowVector.h, idx-vector.cc, idx-vector.h, intNDArray.cc, intNDArray.h, liboctave-build-info.h, liboctave-build-info.in.cc, CollocWt.cc, CollocWt.h, DAE.h, DAEFunc.h, DAERT.h, DAERTFunc.h, DASPK.cc, DASPK.h, DASRT.cc, DASRT.h, DASSL.cc, DASSL.h, DET.h, EIG.h, LSODE.cc, LSODE.h, ODE.h, ODEFunc.h, ODES.h, ODESFunc.h, Quad.h, aepbalance.cc, aepbalance.h, base-dae.h, base-de.h, chol.cc, chol.h, eigs-base.cc, fEIG.h, gepbalance.h, gsvd.cc, gsvd.h, hess.h, lu.cc, lu.h, oct-fftw.cc, oct-fftw.h, oct-rand.cc, oct-rand.h, oct-spparms.cc, oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randmtzig.cc, randmtzig.h, schur.h, sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc, sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h, file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h, lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h, oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc, oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h, action-container.h, base-list.h, caseless-str.h, cmd-edit.cc, cmd-edit.h, cmd-hist.cc, cmd-hist.h, data-conv.cc, file-info.h, glob-match.cc, glob-match.h, kpse.cc, kpse.h, lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.cc, lo-ieee.h, lo-regexp.cc, lo-regexp.h, oct-inttypes.cc, oct-inttypes.h, oct-mutex.cc, oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sort.cc, oct-sort.h, oct-sparse.cc, octave-preserve-stream-state.h, pathsearch.cc, pathsearch.h, quit.cc, singleton-cleanup.cc, singleton-cleanup.h, str-vec.cc, str-vec.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc, url-transfer.h, version.cc, version.in.h, cxx-signal-helpers.cc, acinclude.m4, main-cli.cc, main-gui.cc, main.in.cc, mkoctfile.in.cc, octave-build-info.h, octave-build-info.in.cc, octave-config.in.cc, octave-svgconvert.cc, shared-fcns.h: maint: Eliminate "(void)" in C++ function prototypes/declarations.
author Rik <rik@octave.org>
date Tue, 24 Jan 2023 17:19:44 -0800
parents 3a23b89bd21d
children 49d21a7b25a8
line wrap: on
line source

////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2014-2023 The Octave Project Developers
//
// See the file COPYRIGHT.md in the top-level directory of this
// distribution or <https://octave.org/copyright/>.
//
// 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 <QApplication>
#include <QDialog>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QHeaderView>
#include <QKeyEvent>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
#include <QVBoxLayout>

#include "gui-preferences-sc.h"
#include "gui-settings.h"
#include "shortcuts-tree-widget.h"

OCTAVE_BEGIN_NAMESPACE(octave)

// enter_shortcut:
// class derived from QLineEdit for directly entering key sequences which

enter_shortcut::enter_shortcut (QWidget *p) : QLineEdit (p)
{
  m_direct_shortcut = true;      // the shortcut is directly entered
  m_shift_modifier = false;      // the shift modifier is not added
}

// new keyPressEvent
void enter_shortcut::keyPressEvent (QKeyEvent *e)
{
  if (! m_direct_shortcut)
    {
      QLineEdit::keyPressEvent (e);
      return;
    }

  if (e->type () == QEvent::KeyPress)
    {
      int key = e->key ();

      if (key == Qt::Key_unknown || key == 0)
        return;

      Qt::KeyboardModifiers modifiers = QGuiApplication::keyboardModifiers (); //e->modifiers ();

      if (m_shift_modifier || (modifiers & Qt::ShiftModifier))
        key += Qt::SHIFT;
      if (modifiers & Qt::ControlModifier)
        key += Qt::CTRL;
      if (modifiers & Qt::AltModifier)
        key += Qt::ALT;
      if (modifiers & Qt::MetaModifier)
        key += Qt::META;

      setText (QKeySequence (key).toString ());
    }
}

// slot for checkbox whether the shortcut is directly entered or not
void enter_shortcut::handle_direct_shortcut (int state)
{
  if (state)
    m_direct_shortcut = true;  // the shortcut is directly entered
  else
    m_direct_shortcut = false; // the shortcut has to be written as text
}

// slot for checkbox whether the shift modifier should be added
void enter_shortcut::handle_shift_modifier (int state)
{
  if (state)
    m_shift_modifier = true;  // the shortcut is directly entered
  else
    m_shift_modifier = false; // the shortcut has to be written as text
}

tree_widget_shortcut_item::tree_widget_shortcut_item
(QTreeWidgetItem *parent, const sc_pref& scpref, const QString& actual_text)
  : QTreeWidgetItem (parent), m_settings_key (scpref.settings_key ())
{
  // set a slightly transparent foreground for default columns
  QColor fg = QColor (foreground (DEFAULT_COLUMN).color ());
  fg.setAlpha (128);
  setForeground (DEFAULT_COLUMN, QBrush (fg));

  // write the shortcuts
  set_description (scpref.description ());
  set_default_text (scpref.def_text ());
  set_actual_text (actual_text);
}

QString tree_widget_shortcut_item::settings_key () const
{
  return m_settings_key;
}

QString tree_widget_shortcut_item::description () const
{
  return text (DESCRIPTION_COLUMN);
}

void tree_widget_shortcut_item::set_description (const QString& text)
{
  setText (DESCRIPTION_COLUMN, text);
}

QString tree_widget_shortcut_item::default_text () const
{
  return text (DEFAULT_COLUMN);
}

void tree_widget_shortcut_item::set_default_text (const QString& text)
{
  setText (DEFAULT_COLUMN, text);
}

QString tree_widget_shortcut_item::actual_text () const
{
  return text (ACTUAL_COLUMN);
}

void tree_widget_shortcut_item::set_actual_text (const QString& text)
{
  setText (ACTUAL_COLUMN, text);
}

shortcut_edit_dialog::shortcut_edit_dialog
  (tree_widget_shortcut_item *shortcut_item, QWidget *parent)
  : QDialog (parent), m_shortcut_item (shortcut_item),
    m_settings_key (shortcut_item->settings_key ())
{
  setAttribute (Qt::WA_DeleteOnClose);

  setWindowTitle (tr ("Enter new Shortcut"));

  QVBoxLayout *box = new QVBoxLayout (this);

  box->setSpacing (2);
  box->setContentsMargins (12, 12, 12, 12);

  QLabel *help = new QLabel (tr ("Apply the desired shortcut or click "
                                 "on the right button to reset the "
                                 "shortcut to its default. (%1)")
                             .arg (m_settings_key));

  help->setWordWrap (true);

  box->addWidget (help);

  QCheckBox *direct
    = new QCheckBox (tr ("Enter shortcut directly by performing it"));

  QCheckBox *shift
    = new QCheckBox (tr ("Add Shift modifier\n"
                         "(allows one to enter number keys)"));

  shift->setStyleSheet
    ("QCheckBox::indicator { subcontrol-position: left top; }");

  connect (direct, &QCheckBox::clicked, shift, &QCheckBox::setEnabled);

  direct->setCheckState (Qt::Checked);

  box->addWidget (direct);
  box->addWidget (shift);

  box->addSpacing (15);

  QGridLayout *grid = new QGridLayout ();

  QLabel *actual = new QLabel (tr ("Actual shortcut"));

  m_edit_actual = new enter_shortcut (this);
  m_edit_actual->setAlignment (Qt::AlignHCenter);

  grid->addWidget (actual, 0, 0);
  grid->addWidget (m_edit_actual, 0, 1);

  QLabel *def = new QLabel (tr ("Default shortcut"));

  QLabel *label_default = new QLabel (this);
  label_default->setAlignment (Qt::AlignHCenter);

  grid->addWidget (def, 1, 0);
  grid->addWidget (label_default, 1, 1);

  QPushButton *set_default = new QPushButton (tr ("Set to default"));

  connect (set_default, &QPushButton::clicked,
           this, &shortcut_edit_dialog::set_default_shortcut);

  grid->addWidget (set_default, 0, 2);

  box->addLayout (grid);
  box->addSpacing (18);

  QDialogButtonBox *button_box = new QDialogButtonBox (QDialogButtonBox::Ok
                                                       | QDialogButtonBox::Cancel);
  QList<QAbstractButton *> buttons = button_box->buttons ();
  for (int i = 0; i < buttons.count (); i++)
    buttons.at (i)->setShortcut (QKeySequence ());

  connect (button_box, &QDialogButtonBox::accepted,
           this, &QDialog::accept);

  connect (button_box, &QDialogButtonBox::rejected,
           this, &QDialog::reject);

  box->addWidget (button_box);

  setLayout (box);

  connect (direct, &QCheckBox::stateChanged,
           m_edit_actual, &enter_shortcut::handle_direct_shortcut);

  connect (shift, &QCheckBox::stateChanged,
           m_edit_actual, &enter_shortcut::handle_shift_modifier);

  connect (this, &QDialog::finished,
           this, &shortcut_edit_dialog::finished);

  gui_settings settings;

  const sc_pref scpref = all_shortcut_preferences::value (m_settings_key);

  QString actual_text = settings.sc_value (scpref);

  m_default_text = scpref.def_text ();

  m_edit_actual->setText (actual_text);
  label_default->setText (m_default_text);

  m_edit_actual->setFocus ();

  setFocusProxy (m_edit_actual);
}

void shortcut_edit_dialog::finished (int result)
{
  if (result == QDialog::Rejected)
    return;

  // Check whether the chosen shortcut is already in use either in the
  // current context (section of the shortcut settings) or as a global
  // (main_) shortcut.  This job might have been easier if we had
  // organized the sections as child groups instead of using a colon in
  // the settings key to separate the section from the shortcut name.

 // Note that m_settings_key doesn't begin with the sc_group prefix.

  QString my_section = get_shortcut_section (m_settings_key);
  QString actual_text = m_edit_actual->text ();

  bool conflict = false;
  QString other_settings_key;

  gui_settings settings;

  settings.beginGroup (sc_group);
  const QStringList shortcut_settings_keys = settings.allKeys ();
  settings.endGroup ();

  for (const auto& settings_key : shortcut_settings_keys)
    {
      if (settings_key == m_settings_key)
        continue;

      QString section = get_shortcut_section (settings_key);

      if (section == my_section || section.startsWith ("main_"))
        {
          QString shortcut_text
            = settings.value (sc_group + "/" + settings_key).toString ();

          if (shortcut_text == actual_text)
            {
              other_settings_key = settings_key;
              conflict = true;
            }
        }
    }

  if (conflict)
    {
      // We only need the description of the other shortcut, not the
      // complete sc_pref info.

      const sc_pref other_scpref
        = all_shortcut_preferences::value (other_settings_key);

      int ret = QMessageBox::warning (this, tr ("Double Shortcut"),
                                      tr ("The chosen shortcut\n  \"%1\"\n"
                                          "is already used for the action\n  \"%2\".\n"
                                          "Do you want to use the shortcut and remove it "
                                          "from the previous action?")
                                      .arg (actual_text)
                                      .arg (other_scpref.description ()),
                                      QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);

      if (ret == QMessageBox::Yes)
        emit set_shortcut (other_settings_key, "");
      else
        return;
    }

  m_shortcut_item->set_actual_text (actual_text);
}

void shortcut_edit_dialog::set_default_shortcut ()
{
  // Just remove user-set value so that the default will be used.
  m_edit_actual->setText ("");
}

shortcuts_tree_widget::shortcuts_tree_widget (QWidget *parent)
  : QTreeWidget (parent)
{
  QHash <QString, QTreeWidgetItem *> level_hash;

  header ()->setSectionResizeMode (QHeaderView::ResizeToContents);

  int dsc_col = tree_widget_shortcut_item::DESCRIPTION_COLUMN;

  QTreeWidgetItem *main = new QTreeWidgetItem (this);
  main->setText (dsc_col, tr ("Global"));
  main->setExpanded (true);

  QTreeWidgetItem *main_file = new QTreeWidgetItem (main);
  main_file->setText (dsc_col, tr ("File Menu"));

  QTreeWidgetItem *main_edit = new QTreeWidgetItem (main);
  main_edit->setText (dsc_col, tr ("Edit Menu"));

  QTreeWidgetItem *main_debug = new QTreeWidgetItem (main);
  main_debug->setText (dsc_col, tr ("Debug Menu"));

  QTreeWidgetItem *main_tools = new QTreeWidgetItem (main);
  main_tools->setText (dsc_col, tr ("Tools Menu"));

  QTreeWidgetItem *main_window = new QTreeWidgetItem (main);
  main_window->setText (dsc_col, tr ("Window Menu"));

  QTreeWidgetItem *main_help = new QTreeWidgetItem (main);
  main_help->setText (dsc_col, tr ("Help Menu"));

  QTreeWidgetItem *main_news = new QTreeWidgetItem (main);
  main_news->setText (dsc_col, tr ("News Menu"));

  QTreeWidgetItem *main_dock_widgets = new QTreeWidgetItem (main);
  main_dock_widgets->setText (dsc_col, tr ("Handling of Dock Widgets"));

  QTreeWidgetItem *main_tabs = new QTreeWidgetItem (main);
  main_tabs->setText (dsc_col, tr ("Tab Handling in Dock Widgets"));

  QTreeWidgetItem *main_find = new QTreeWidgetItem (main);
  main_find->setText (dsc_col, tr ("Find & Replace in Dock Widgets"));

  QTreeWidgetItem *main_zoom = new QTreeWidgetItem (main);
  main_zoom->setText (dsc_col, tr ("Zooming in Editor and Documentation"));

  level_hash[sc_main_file] = main_file;
  level_hash[sc_main_edit] = main_edit;
  level_hash[sc_main_debug] = main_debug;
  level_hash[sc_main_tools] = main_tools;
  level_hash[sc_main_window] = main_window;
  level_hash[sc_main_help] = main_help;
  level_hash[sc_main_news] = main_news;
  level_hash[sc_dock_widget] = main_dock_widgets;
  level_hash[sc_edit_tabs] = main_tabs;
  level_hash[sc_edit_find] = main_find;
  level_hash[sc_edit_zoom] = main_zoom;

  QTreeWidgetItem *editor = new QTreeWidgetItem (this);
  editor->setText (dsc_col, tr ("Editor"));
  editor->setExpanded (true);

  QTreeWidgetItem *editor_file = new QTreeWidgetItem (editor);
  editor_file->setText (dsc_col, tr ("File Menu"));

  QTreeWidgetItem *editor_edit = new QTreeWidgetItem (editor);
  editor_edit->setText (dsc_col, tr ("Edit Menu"));

  QTreeWidgetItem *editor_view = new QTreeWidgetItem (editor);
  editor_view->setText (dsc_col, tr ("View Menu"));

  QTreeWidgetItem *editor_debug = new QTreeWidgetItem (editor);
  editor_debug->setText (dsc_col, tr ("Debug Menu"));

  QTreeWidgetItem *editor_run = new QTreeWidgetItem (editor);
  editor_run->setText (dsc_col, tr ("Run Menu"));

  QTreeWidgetItem *editor_help = new QTreeWidgetItem (editor);
  editor_help->setText (dsc_col, tr ("Help Menu"));

  level_hash[sc_edit_file] = editor_file;
  level_hash[sc_edit_edit] = editor_edit;
  level_hash[sc_edit_view] = editor_view;
  level_hash[sc_edit_debug] = editor_debug;
  level_hash[sc_edit_run] = editor_run;
  level_hash[sc_edit_help] = editor_help;

  QTreeWidgetItem *doc = new QTreeWidgetItem (this);
  doc->setText (dsc_col, tr ("Documentation Viewer"));
  doc->setExpanded (true);

  QTreeWidgetItem *doc_browser = new QTreeWidgetItem (doc);
  doc_browser->setText (dsc_col, tr ("Browser"));

  level_hash[sc_doc] = doc_browser;

  connect (this, &QTreeWidget::itemDoubleClicked,
           this, &shortcuts_tree_widget::edit_selection);

  const QList<QString> shortcut_settings_keys
    = all_shortcut_preferences::keys ();

  gui_settings settings;

  settings.beginGroup (sc_group);

  for (const auto& settings_key : shortcut_settings_keys)
    {
      QTreeWidgetItem *section = level_hash[settings_key.section (':', 0, 0)];

      // handle sections which have changed and do not correspond to the
      // previously defined keyname
      if (section == editor_file)
        {
          // Closing tabs now in global tab handling section
          if (settings_key.contains (sc_edit_file_cl))
            section = main_tabs;
        }
      else if (section == editor_edit)
        {
          // Find & replace now in global file & replace handling section
          if (settings_key.contains (sc_edit_edit_find))
            section = main_find;
        }
      else if (section == editor_view)
        {
          // Zooming now in global zoom handling section
          if (settings_key.contains (sc_edit_view_zoom))
            section = main_zoom;
        }

      // We don't want to apply default value here.
      QString actual_text = settings.value (settings_key).toString ();

      const sc_pref scpref = all_shortcut_preferences::value (settings_key);

      // Inserts itself in the tree widget in SECTION.  The parent
      // object will delete it.
      new tree_widget_shortcut_item (section, scpref, actual_text);
    }

  settings.endGroup ();
}

void
shortcuts_tree_widget::edit_selection (QTreeWidgetItem *item, int col)
{
  if (col != 2)
    return;

  tree_widget_shortcut_item *shortcut_item
    = dynamic_cast<tree_widget_shortcut_item *> (item);

  if (! shortcut_item)
    return;  // top-level-item clicked

  shortcut_edit_dialog *dialog
    = new shortcut_edit_dialog (shortcut_item);

  connect (dialog, &shortcut_edit_dialog::set_shortcut,
           this, &shortcuts_tree_widget::update_widget_value);

  dialog->show ();
}

void shortcuts_tree_widget::update_widget_value (const QString& settings_key,
                                                 const QString& sc_text)
{
  tree_widget_shortcut_item *item = get_item (settings_key);

  if (item)
    item->set_actual_text (sc_text);
}

tree_widget_shortcut_item *
shortcuts_tree_widget::get_item (const QString& settings_key)
{
  // There aren't many shortcuts so iterating over all of them to find
  // an individual item isn't a big performance issue.  If we had many
  // more items we could use a QHash <settings_key, sc_pref> data member.

  tree_widget_shortcut_item *item = nullptr;

  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
  while (*it)
    {
      tree_widget_shortcut_item *shortcut_item
        = dynamic_cast<tree_widget_shortcut_item *> (*it);

      if (settings_key == shortcut_item->settings_key ())
        {
          item = shortcut_item;
          break;
        }

      it++;
    }

  // FIXME: Should it be an error to not find a match?

  if (! item)
    qWarning () << (tr ("item %1 not found in shortcut settings dialog")
                    .arg (settings_key));

  return item;
}

void shortcuts_tree_widget::update_settings_value (gui_settings& settings,
                                                   const QString& settings_key)
{
  tree_widget_shortcut_item *item = get_item (settings_key);

  if (item)
    settings.setValue (settings_key, item->actual_text ());
}

// Refresh the tree view with values from the settings object.

void shortcuts_tree_widget::import_shortcuts (gui_settings& settings)
{
  settings.beginGroup (sc_group);

  const QStringList shortcut_settings_keys = settings.allKeys ();

  for (const auto& settings_key : shortcut_settings_keys)
    {
      // We don't want to apply default value here.
      QString sc_text = settings.value (settings_key).toString ();

      update_widget_value (settings_key, sc_text);
    }

  settings.endGroup ();

  bool sc_ctrld = false;

  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
  while (*it)
    {
      tree_widget_shortcut_item *shortcut_item
        = dynamic_cast<tree_widget_shortcut_item *> (*it);

      if (! shortcut_item)
        continue;

      QString settings_key = shortcut_item->settings_key ();
      QString sc_text = shortcut_item->actual_text ();

      if (sc_text.isEmpty ())
        sc_text = shortcut_item->default_text ();

      QString section = get_shortcut_section (settings_key);

      // special: check main-window for Ctrl-D (Terminal)
      if (section.startsWith ("main_")
          && QKeySequence (sc_text) == QKeySequence (Qt::ControlModifier+Qt::Key_D))

        sc_ctrld = true;

      it++;
    }

  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);

  settings.sync ();
}

// Export all shortcuts from the tree view to the settings object.

void shortcuts_tree_widget::export_shortcuts (gui_settings& settings)
{
  settings.beginGroup (sc_group);

  bool sc_ctrld = false;

  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
  while (*it)
    {
      tree_widget_shortcut_item *shortcut_item
        = dynamic_cast<tree_widget_shortcut_item *> (*it);

      if (! shortcut_item)
        continue;

      QString settings_key = shortcut_item->settings_key ();
      QString sc_text = shortcut_item->actual_text ();

      if (sc_text.isEmpty ())
        sc_text = shortcut_item->default_text ();
      else
        settings.setValue (settings_key, sc_text);

      QString section = get_shortcut_section (settings_key);

      // special: check main-window for Ctrl-D (Terminal)
      if (section.startsWith ("main_")
          && QKeySequence (sc_text) == QKeySequence (Qt::ControlModifier+Qt::Key_D))

        sc_ctrld = true;

      it++;
    }

  settings.endGroup ();

  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);

  settings.sync ();
}

// Clear all user-defined settings from the tree widget and the
// application settings.

void shortcuts_tree_widget::set_default_shortcuts ()
{
  gui_settings settings;

  settings.beginGroup (sc_group);

  settings.remove ("");

  settings.endGroup ();

  bool sc_ctrld = false;

  QTreeWidgetItemIterator it (this, QTreeWidgetItemIterator::NoChildren);
  while (*it)
    {
      tree_widget_shortcut_item *shortcut_item
        = dynamic_cast<tree_widget_shortcut_item *> (*it);

      if (! shortcut_item)
        continue;

      QString settings_key = shortcut_item->settings_key ();

      shortcut_item->set_actual_text ("");

      QString sc_text = shortcut_item->default_text ();

      QString section = get_shortcut_section (settings_key);

      // special: check main-window for Ctrl-D (Terminal)
      if (section.startsWith ("main_")
          && QKeySequence (sc_text) == QKeySequence (Qt::ControlModifier+Qt::Key_D))

        sc_ctrld = true;

      it++;
    }

  settings.setValue (sc_main_ctrld.settings_key (), sc_ctrld);

  settings.sync ();
}

// For each key found in application settings object, transfer
// corresponding setting to the application settings object.

void shortcuts_tree_widget::write_settings ()
{
  gui_settings settings;

  export_shortcuts (settings);
}

OCTAVE_END_NAMESPACE(octave)