1 //////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 2011-2021 The Octave Project Developers 4 // 5 // See the file COPYRIGHT.md in the top-level directory of this 6 // distribution or <https://octave.org/copyright/>. 7 // 8 // This file is part of Octave. 9 // 10 // Octave is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 3 of the License, or 13 // (at your option) any later version. 14 // 15 // Octave is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Octave; see the file COPYING. If not, see 22 // <https://www.gnu.org/licenses/>. 23 // 24 //////////////////////////////////////////////////////////////////////// 25 26 #if defined (HAVE_CONFIG_H) 27 # include "config.h" 28 #endif 29 30 #include <iostream> 31 32 #include <QTreeWidget> 33 34 #include "gui-preferences-ws.h" 35 #include "gui-settings.h" 36 #include "octave-qobject.h" 37 #include "workspace-model.h" 38 39 #include "syminfo.h" 40 #include "utils.h" 41 42 namespace octave 43 { workspace_model(base_qobject & oct_qobj,QObject * p)44 workspace_model::workspace_model (base_qobject& oct_qobj, QObject *p) 45 : QAbstractTableModel (p), m_octave_qobj (oct_qobj) 46 { 47 m_columnNames.append (tr ("Name")); 48 m_columnNames.append (tr ("Class")); 49 m_columnNames.append (tr ("Dimension")); 50 m_columnNames.append (tr ("Value")); 51 m_columnNames.append (tr ("Attribute")); 52 53 // Initialize the background and foreground colors of special 54 // classes in the workspace view. The structure is 55 // m_storage_class_colors(1,2,...,colors): background colors 56 // m_storage_class_colors(colors+1,...,2*colors): foreground colors 57 for (unsigned int i = 0; i < 2*ws_colors_count; i++) 58 m_storage_class_colors.append (QColor (Qt::white)); 59 60 } 61 62 int rowCount(const QModelIndex &) const63 workspace_model::rowCount (const QModelIndex&) const 64 { 65 return m_symbols.size (); 66 } 67 68 int columnCount(const QModelIndex &) const69 workspace_model::columnCount (const QModelIndex&) const 70 { 71 return m_columnNames.size (); 72 } 73 74 Qt::ItemFlags flags(const QModelIndex & idx) const75 workspace_model::flags (const QModelIndex& idx) const 76 { 77 Qt::ItemFlags retval = Qt::NoItemFlags; 78 79 if (idx.isValid ()) 80 { 81 retval |= Qt::ItemIsEnabled; 82 83 if (m_top_level && idx.column () == 0) 84 retval |= Qt::ItemIsSelectable; 85 } 86 87 return retval; 88 } 89 90 QVariant headerData(int section,Qt::Orientation orientation,int role) const91 workspace_model::headerData (int section, Qt::Orientation orientation, 92 int role) const 93 { 94 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) 95 return m_columnNames[section]; 96 else 97 return QVariant (); 98 } 99 100 QVariant data(const QModelIndex & idx,int role) const101 workspace_model::data (const QModelIndex& idx, int role) const 102 { 103 QVariant retval; 104 105 if (idx.isValid ()) 106 { 107 if ((role == Qt::BackgroundColorRole || role == Qt::ForegroundRole) 108 && m_enable_colors) 109 { 110 int actual_class 111 = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ()); 112 if (actual_class >= 0) 113 { 114 // Valid class: Get background (normal indexes) or foreground 115 // color (indexes with offset) 116 if (role == Qt::ForegroundRole) 117 actual_class += ws_colors_count; 118 119 return QVariant (m_storage_class_colors.at (actual_class)); 120 } 121 else 122 return retval; 123 } 124 125 if (role == Qt::DisplayRole 126 || (idx.column () == 0 && role == Qt::EditRole) 127 || (idx.column () == 0 && role == Qt::ToolTipRole)) 128 { 129 switch (idx.column ()) 130 { 131 case 0: 132 if (role == Qt::ToolTipRole) 133 retval 134 = QVariant (tr ("Right click to copy, rename, or display")); 135 else 136 retval = QVariant (m_symbols[idx.row ()]); 137 break; 138 139 case 1: 140 retval = QVariant (m_class_names[idx.row ()]); 141 break; 142 143 case 2: 144 retval = QVariant (m_dimensions[idx.row ()]); 145 break; 146 147 case 3: 148 retval = QVariant (m_values[idx.row ()]); 149 break; 150 151 case 4: 152 { 153 QString sclass; 154 155 int actual_class 156 = ws_class_chars.indexOf (m_scopes[idx.row ()].toLatin1 ()); 157 158 if (actual_class >= 0) 159 sclass = ws_color_names.at (actual_class); 160 161 if (m_complex_flags[idx.row ()]) 162 { 163 if (sclass.isEmpty ()) 164 sclass = tr ("complex"); 165 else 166 sclass += ", " + tr ("complex"); 167 } 168 169 retval = QVariant (sclass); 170 } 171 break; 172 } 173 } 174 } 175 176 return retval; 177 } 178 179 void set_workspace(bool top_level,bool,const symbol_info_list & syminfo)180 workspace_model::set_workspace (bool top_level, bool /* debug */, 181 const symbol_info_list& syminfo) 182 { 183 clear_data (); 184 185 m_top_level = top_level; 186 m_syminfo_list = syminfo; 187 188 update_table (); 189 } 190 191 void clear_workspace(void)192 workspace_model::clear_workspace (void) 193 { 194 clear_data (); 195 update_table (); 196 } 197 198 void notice_settings(const gui_settings * settings)199 workspace_model::notice_settings (const gui_settings *settings) 200 { 201 m_enable_colors = settings->value (ws_enable_colors).toBool (); 202 203 for (int i = 0; i < ws_colors_count; i++) 204 { 205 QColor setting_color = settings->value (ws_colors[i].key, 206 ws_colors[i].def).value<QColor> (); 207 208 QPalette p (setting_color); 209 m_storage_class_colors.replace (i,setting_color); 210 211 QColor fg_color = p.color (QPalette::WindowText); 212 m_storage_class_colors.replace (i + ws_colors_count, fg_color); 213 214 } 215 } 216 217 void clear_data(void)218 workspace_model::clear_data (void) 219 { 220 m_top_level = false; 221 m_syminfo_list = symbol_info_list (); 222 m_scopes = QString (); 223 m_symbols = QStringList (); 224 m_class_names = QStringList (); 225 m_dimensions = QStringList (); 226 m_values = QStringList (); 227 m_complex_flags = QIntList (); 228 } 229 230 void update_table(void)231 workspace_model::update_table (void) 232 { 233 beginResetModel (); 234 235 for (const auto& syminfo : m_syminfo_list) 236 { 237 std::string nm = syminfo.name (); 238 239 octave_value val = syminfo.value (); 240 241 // FIXME: fix size for objects, see kluge in ov.cc 242 Matrix sz = val.size (); 243 dim_vector dv = dim_vector::alloc (sz.numel ()); 244 for (octave_idx_type i = 0; i < dv.ndims (); i++) 245 dv(i) = sz(i); 246 247 char storage = ' '; 248 if (syminfo.is_formal ()) 249 storage = 'a'; 250 else if (syminfo.is_global ()) 251 storage = 'g'; 252 else if (syminfo.is_persistent ()) 253 storage = 'p'; 254 255 std::ostringstream buf; 256 val.short_disp (buf); 257 std::string short_disp_str = buf.str (); 258 259 m_scopes.append (storage); 260 m_symbols.append (QString::fromStdString (nm)); 261 m_class_names.append (QString::fromStdString (val.class_name ())); 262 m_dimensions.append (QString::fromStdString (dv.str ())); 263 m_values.append (QString::fromStdString (short_disp_str)); 264 m_complex_flags.append (val.iscomplex ()); 265 } 266 267 endResetModel (); 268 269 emit model_changed (); 270 } 271 } 272