GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
files-dock-widget.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2011-2022 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 <QApplication>
31#include <QClipboard>
32#include <QCompleter>
33#include <QDebug>
34#include <QDesktopServices>
35#include <QFileDialog>
36#include <QFileInfo>
37#include <QHeaderView>
38#include <QInputDialog>
39#include <QLineEdit>
40#include <QMenu>
41#include <QMessageBox>
42#include <QProcess>
43#include <QSizePolicy>
44#include <QToolButton>
45#include <QUrl>
46
47#include "files-dock-widget.h"
48#include "gui-preferences-fb.h"
50#include "octave-qobject.h"
51#include "octave-qtutils.h"
53
54#include "oct-env.h"
55
56namespace octave
57{
59 {
60 public:
61
63
64 ~FileTreeViewer (void) = default;
65
66 void mousePressEvent (QMouseEvent *e)
67 {
68 if (e->button () != Qt::RightButton)
69 QTreeView::mousePressEvent (e);
70 }
71 };
72
74 : octave_dock_widget ("FilesDockWidget", p, oct_qobj)
75 {
76 setWindowIcon (QIcon (":/actions/icons/logo.png"));
77 set_title (tr ("File Browser"));
78 setToolTip (tr ("Browse your files"));
79
80 m_sig_mapper = nullptr;
81
82 m_columns_shown = QStringList ();
83 m_columns_shown.append (tr ("File size"));
84 m_columns_shown.append (tr ("File type"));
85 m_columns_shown.append (tr ("Date modified"));
86 m_columns_shown.append (tr ("Show hidden"));
87 m_columns_shown.append (tr ("Alternating row colors"));
88
89 m_columns_shown_keys = QStringList ();
95
102
103 QWidget *container = new QWidget (this);
104
105 setWidget (container);
106
107 // Create a toolbar
108 m_navigation_tool_bar = new QToolBar ("", container);
109 m_navigation_tool_bar->setAllowedAreas (Qt::TopToolBarArea);
110 m_navigation_tool_bar->setMovable (false);
111
113 m_current_directory->setToolTip (tr ("Enter the path or filename"));
114 m_current_directory->setEditable (true);
115 m_current_directory->setMaxCount (MaxMRUDirs);
116 m_current_directory->setInsertPolicy (QComboBox::NoInsert);
117 m_current_directory->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
118 QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
119 m_current_directory->setSizePolicy (sizePol);
120
122
123 QAction *directory_up_action
124 = new QAction (rmgr.icon ("go-up"), "", m_navigation_tool_bar);
125 directory_up_action->setToolTip (tr ("One directory up"));
126
128 = new QAction (rmgr.icon ("go-first"), tr ("Show Octave directory"),
130 m_sync_browser_directory_action->setToolTip (tr ("Go to current Octave directory"));
131 m_sync_browser_directory_action->setEnabled (false);
132
134 = new QAction (rmgr.icon ("go-last"), tr ("Set Octave directory"),
136 m_sync_octave_directory_action->setToolTip (tr ("Set Octave directory to current browser directory"));
137 m_sync_octave_directory_action->setEnabled (false);
138
139 QToolButton *popdown_button = new QToolButton ();
140 popdown_button->setToolTip (tr ("Actions on current directory"));
141 QMenu *popdown_menu = new QMenu ();
142 popdown_menu->addAction (rmgr.icon ("user-home"),
143 tr ("Show Home Directory"), this,
144 SLOT (popdownmenu_home (bool)));
145 popdown_menu->addAction (m_sync_browser_directory_action);
146 popdown_menu->addAction (m_sync_octave_directory_action);
147 popdown_button->setMenu (popdown_menu);
148 popdown_button->setPopupMode (QToolButton::InstantPopup);
149 popdown_button->setDefaultAction (new QAction (rmgr.icon ("applications-system"),
151
152 popdown_menu->addSeparator ();
153 popdown_menu->addAction (rmgr.icon ("folder"),
154 tr ("Set Browser Directory..."),
156 popdown_menu->addSeparator ();
157 popdown_menu->addAction (rmgr.icon ("edit-find"),
158 tr ("Find Files..."),
160 popdown_menu->addSeparator ();
161 popdown_menu->addAction (rmgr.icon ("document-new"),
162 tr ("New File..."),
164 popdown_menu->addAction (rmgr.icon ("folder-new"),
165 tr ("New Directory..."),
167
169 m_navigation_tool_bar->addAction (directory_up_action);
170 m_navigation_tool_bar->addWidget (popdown_button);
171
172 connect (directory_up_action, &QAction::triggered,
174 connect (m_sync_octave_directory_action, &QAction::triggered,
176 connect (m_sync_browser_directory_action, &QAction::triggered,
178
180 // FIXME: what should happen if settings is 0?
181
182 // Create the QFileSystemModel starting in the desired directory
183 QDir startup_dir; // take current dir
184
185 if (settings->value (fb_restore_last_dir).toBool ())
186 {
187 // restore last dir from previous session
188 QStringList last_dirs
189 = settings->value (fb_mru_list.key).toStringList ();
190 if (last_dirs.length () > 0)
191 startup_dir = QDir (last_dirs.at (0)); // last dir in previous session
192 }
193 else if (! settings->value (fb_startup_dir).toString ().isEmpty ())
194 {
195 // do not restore but there is a startup dir configured
196 startup_dir = QDir (settings->value (fb_startup_dir.key).toString ());
197 }
198
199 if (! startup_dir.exists ())
200 {
201 // the configured startup dir does not exist, take actual one
202 startup_dir = QDir ();
203 }
204
205 m_file_system_model = new QFileSystemModel (this);
206 m_file_system_model->setResolveSymlinks (false);
207 m_file_system_model->setFilter (
208 QDir::System | QDir::NoDotAndDotDot | QDir::AllEntries);
209 QModelIndex rootPathIndex
210 = m_file_system_model->setRootPath (startup_dir.absolutePath ());
211
212 // Attach the model to the QTreeView and set the root index
213 m_file_tree_view = new FileTreeViewer (container);
214 m_file_tree_view->setSelectionMode (QAbstractItemView::ExtendedSelection);
216 m_file_tree_view->setRootIndex (rootPathIndex);
217 m_file_tree_view->setSortingEnabled (true);
218 m_file_tree_view->setAlternatingRowColors (true);
219 m_file_tree_view->setAnimated (true);
220 m_file_tree_view->setToolTip (tr ("Double-click to open file/folder, right click for alternatives"));
221
222 // get sort column and order as well as column state (order and width)
223
224 m_file_tree_view->sortByColumn
225 (settings->value (fb_sort_column).toInt (),
226 static_cast<Qt::SortOrder> (settings->value (fb_sort_order).toUInt ()));
227 // FIXME: use value<Qt::SortOrder> instead of static cast after
228 // dropping support of Qt 5.4
229
230 if (settings->contains (fb_column_state.key))
231 m_file_tree_view->header ()->restoreState
232 (settings->value (fb_column_state.key).toByteArray ());
233
234 // Set header properties for sorting
235 m_file_tree_view->header ()->setSectionsClickable (true);
236 m_file_tree_view->header ()->setSectionsMovable (true);
237 m_file_tree_view->header ()->setSortIndicatorShown (true);
238
239 QStringList mru_dirs =
240 settings->value (fb_mru_list.key).toStringList ();
241 m_current_directory->addItems (mru_dirs);
242
243 m_current_directory->setEditText
244 (m_file_system_model->fileInfo (rootPathIndex). absoluteFilePath ());
245
246 connect (m_file_tree_view, &FileTreeViewer::activated,
248
249 // add context menu to tree_view
250 m_file_tree_view->setContextMenuPolicy (Qt::CustomContextMenu);
251 connect (m_file_tree_view, &FileTreeViewer::customContextMenuRequested,
253
254 m_file_tree_view->header ()->setContextMenuPolicy (Qt::CustomContextMenu);
255 connect (m_file_tree_view->header (),
256 &QHeaderView::customContextMenuRequested,
258
259 // Layout the widgets vertically with the toolbar on top
260 QVBoxLayout *vbox_layout = new QVBoxLayout ();
261 vbox_layout->setSpacing (0);
262 vbox_layout->addWidget (m_navigation_tool_bar);
263 vbox_layout->addWidget (m_file_tree_view);
264 vbox_layout->setMargin (1);
265
266 container->setLayout (vbox_layout);
267
268 // FIXME: Add right-click contextual menus for copying, pasting,
269 // deleting files (and others).
270
271 connect (m_current_directory->lineEdit (), &QLineEdit::returnPressed,
273
274 // FIXME: We could use
275 //
276 // connect (m_current_directory,
277 // QOverload<const QString&>::of (&QComboBox::activated),
278 // this, &files_dock_widget::set_current_directory);
279 //
280 // but referring to QComboBox::activated will generate deprecated
281 // function warnings from GCC. We could also use
282 //
283 // connect (m_current_directory, &QComboBox::textActivated,
284 // this, &files_dock_widget::set_current_directory);
285 //
286 // but the function textActivated was not introduced until Qt 5.14
287 // so we'll need a feature test.
288
289 connect (m_current_directory, SIGNAL (activated (const QString&)),
290 this, SLOT (set_current_directory (const QString&)));
291
292 QCompleter *completer = new QCompleter (m_file_system_model, this);
293 m_current_directory->setCompleter (completer);
294
295 setFocusProxy (m_current_directory);
296
297 m_sync_octave_dir = true; // default, overwritten with notice_settings ()
298 m_octave_dir = "";
299
300 if (! p)
301 make_window ();
302 }
303
305 {
308
309 if (! settings)
310 return;
311
312 int sort_column = m_file_tree_view->header ()->sortIndicatorSection ();
313 Qt::SortOrder sort_order = m_file_tree_view->header ()->sortIndicatorOrder ();
314 settings->setValue (fb_sort_column.key, sort_column);
315 settings->setValue (fb_sort_order.key, sort_order);
316 settings->setValue (fb_column_state.key,
317 m_file_tree_view->header ()->saveState ());
318
319 QStringList dirs;
320 for (int i=0; i< m_current_directory->count (); i++)
321 {
322 dirs.append (m_current_directory->itemText (i));
323 }
324 settings->setValue (fb_mru_list.key, dirs);
325
326 settings->sync ();
327
329
330 if (m_sig_mapper)
331 delete m_sig_mapper;
332 }
333
334 void files_dock_widget::item_double_clicked (const QModelIndex& index)
335 {
336 // Retrieve the file info associated with the model index.
337 QFileInfo fileInfo = m_file_system_model->fileInfo (index);
338 set_current_directory (fileInfo.absoluteFilePath ());
339 }
340
342 {
343 display_directory (dir);
344 }
345
347 {
348 display_directory (m_current_directory->currentText ());
349 }
350
352 {
353 QDir dir
354 = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));
355
356 dir.cdUp ();
357 display_directory (dir.absolutePath ());
358 }
359
361 {
362 QDir dir
363 = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));
364
365 emit displayed_directory_changed (dir.absolutePath ());
366 }
367
369 {
370 display_directory (m_octave_dir, false); // false: no sync of octave dir
371 }
372
374 {
375 m_octave_dir = dir;
377 display_directory (m_octave_dir, false); // false: no sync of octave dir
378 }
379
380 void files_dock_widget::display_directory (const QString& dir,
381 bool set_octave_dir)
382 {
383 QFileInfo fileInfo (dir);
384 if (fileInfo.exists ())
385 {
386 if (fileInfo.isDir ())
387 {
389 index (fileInfo.absoluteFilePath ()));
390 m_file_system_model->setRootPath (fileInfo.absoluteFilePath ());
391 if (m_sync_octave_dir && set_octave_dir)
392 process_set_current_dir (fileInfo.absoluteFilePath ());
393
394 // see if it's in the list, and if it is,
395 // remove it and then put at top of the list
396 int index
397 = m_current_directory->findText (fileInfo.absoluteFilePath ());
398 if (index != -1)
399 {
400 m_current_directory->removeItem (index);
401 }
402 m_current_directory->insertItem (0, fileInfo.absoluteFilePath ());
403 m_current_directory->setCurrentIndex (0);
404 }
405 else
406 {
407 QString abs_fname = fileInfo.absoluteFilePath ();
408
409 QString suffix = fileInfo.suffix ().toLower ();
412 QString ext = settings->value (fb_txt_file_ext).toString ();
413#if defined (HAVE_QT_SPLITBEHAVIOR_ENUM)
414 QStringList extensions = ext.split (";", Qt::SkipEmptyParts);
415#else
416 QStringList extensions = ext.split (";", QString::SkipEmptyParts);
417#endif
418 if (QFile::exists (abs_fname))
419 {
420 if (extensions.contains (suffix))
421 emit open_file (fileInfo.absoluteFilePath ());
422 else
423 emit open_any_signal (abs_fname);
424 }
425 }
426 }
427 }
428
429 void files_dock_widget::open_item_in_app (const QModelIndex& index)
430 {
431 // Retrieve the file info associated with the model index.
432 QFileInfo fileInfo = m_file_system_model->fileInfo (index);
433
434 QString file = fileInfo.absoluteFilePath ();
435
436 QDesktopServices::openUrl (QUrl::fromLocalFile (file));
437 }
438
440 {
443
444 QString key = m_columns_shown_keys.at (col);
445 bool shown = settings->value (key, false).toBool ();
446 settings->setValue (key, ! shown);
447 settings->sync ();
448
449 switch (col)
450 {
451 case 0:
452 case 1:
453 case 2:
454 // toggle column visibility
455 m_file_tree_view->setColumnHidden (col + 1, shown);
456 break;
457 case 3:
458 case 4:
459 // other actions depending on new settings
461 break;
462 }
463 }
464
466 {
467 QMenu menu (this);
468
469 if (m_sig_mapper)
470 delete m_sig_mapper;
471 m_sig_mapper = new QSignalMapper (this);
472
475
476 for (int i = 0; i < m_columns_shown.size (); i++)
477 {
478 QAction *action = menu.addAction (m_columns_shown.at (i),
479 m_sig_mapper, SLOT (map ()));
480 m_sig_mapper->setMapping (action, i);
481 action->setCheckable (true);
482 action->setChecked
483 (settings->value (m_columns_shown_keys.at (i),
484 m_columns_shown_defs.at (i)).toBool ());
485 }
486
487 // FIXME: We could use
488 //
489 // connect (&m_sig_mapper, QOverload<int>::of (&QSignalMapper::mapped),
490 // this, &workspace_view::toggle_header);
491 //
492 // but referring to QSignalMapper::mapped will generate deprecated
493 // function warnings from GCC. We could also use
494 //
495 // connect (&m_sig_mapper, &QSignalMapper::mappedInt,
496 // this, &workspace_view::toggle_header);
497 //
498 // but the function mappedInt was not introduced until Qt 5.15 so
499 // we'll need a feature test.
500
501 connect (m_sig_mapper, SIGNAL (mapped (int)),
502 this, SLOT (toggle_header (int)));
503
504 menu.exec (m_file_tree_view->mapToGlobal (mpos));
505 }
506
508 {
509
510 QMenu menu (this);
511
512 QModelIndex index = m_file_tree_view->indexAt (mpos);
513
514 if (index.isValid ())
515 {
516 QFileInfo info = m_file_system_model->fileInfo (index);
517
518 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
519 QModelIndexList sel = m->selectedRows ();
520
521 // check if item at mouse position is seleccted
522 if (! sel.contains (index))
523 {
524 // is not selected -> clear actual selection and select this item
525 m->setCurrentIndex (index,
526 QItemSelectionModel::Clear
527 | QItemSelectionModel::Select
528 | QItemSelectionModel::Rows);
529 }
530
532
533 // construct the context menu depending on item
534 menu.addAction (rmgr.icon ("document-open"), tr ("Open"),
536
537 if (info.isDir ())
538 {
539 menu.addAction (tr ("Open in System File Explorer"),
541 }
542
543 if (info.isFile ())
544 menu.addAction (tr ("Open in Text Editor"),
546
547 menu.addAction (tr ("Copy Selection to Clipboard"),
549
550 if (info.isFile () && info.suffix () == "m")
551 menu.addAction (rmgr.icon ("media-playback-start"), tr ("Run"),
553
554 if (info.isFile ())
555 menu.addAction (tr ("Load Data"),
557
558 if (info.isDir ())
559 {
560 menu.addSeparator ();
561 menu.addAction (rmgr.icon ("go-first"), tr ("Set Current Directory"),
563
564 QMenu *add_path_menu = menu.addMenu (tr ("Add to Path"));
565
566 add_path_menu->addAction (tr ("Selected Directories"),
567 this, [=] (bool checked) { contextmenu_add_to_path (checked); });
568 add_path_menu->addAction (tr ("Selected Directories and Subdirectories"),
570
571 QMenu *rm_path_menu = menu.addMenu (tr ("Remove from Path"));
572
573 rm_path_menu->addAction (tr ("Selected Directories"),
575 rm_path_menu->addAction (tr ("Selected Directories and Subdirectories"),
577
578 menu.addSeparator ();
579
580 menu.addAction (rmgr.icon ("edit-find"), tr ("Find Files..."),
582 }
583
584 menu.addSeparator ();
585 menu.addAction (tr ("Rename..."),
587 menu.addAction (rmgr.icon ("edit-delete"), tr ("Delete..."),
589
590 if (info.isDir ())
591 {
592 menu.addSeparator ();
593 menu.addAction (rmgr.icon ("document-new"), tr ("New File..."),
595 menu.addAction (rmgr.icon ("folder-new"), tr ("New Directory..."),
597 }
598
599 // show the menu
600 menu.exec (m_file_tree_view->mapToGlobal (mpos));
601
602 }
603 }
604
606 {
607
608 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
609 QModelIndexList rows = m->selectedRows ();
610
611 for (auto it = rows.begin (); it != rows.end (); it++)
612 {
613 QFileInfo file = m_file_system_model->fileInfo (*it);
614 if (file.exists ())
615 display_directory (file.absoluteFilePath ());
616 }
617 }
618
620 {
621
622 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
623 QModelIndexList rows = m->selectedRows ();
624
625 for (auto it = rows.begin (); it != rows.end (); it++)
626 {
627 QFileInfo file = m_file_system_model->fileInfo (*it);
628 if (file.exists ())
629 emit open_file (file.absoluteFilePath ());
630 }
631 }
632
634 {
635 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
636 QModelIndexList rows = m->selectedRows ();
637
638 for (auto it = rows.begin (); it != rows.end (); it++)
639 open_item_in_app (*it);
640 }
641
643 {
644 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
645 QModelIndexList rows = m->selectedRows ();
646
647 QStringList selection;
648
649 for (auto it = rows.begin (); it != rows.end (); it++)
650 {
651 QFileInfo info = m_file_system_model->fileInfo (*it);
652
653 selection << info.fileName ();
654 }
655
656 QClipboard *clipboard = QApplication::clipboard ();
657
658 clipboard->setText (selection.join ("\n"));
659 }
660
662 {
663 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
664 QModelIndexList rows = m->selectedRows ();
665
666 if (rows.size () > 0)
667 {
668 QModelIndex index = rows[0];
669
670 QFileInfo info = m_file_system_model->fileInfo (index);
671
672 emit load_file_signal (info.fileName ());
673 }
674 }
675
677 {
678 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
679 QModelIndexList rows = m->selectedRows ();
680
681 if (rows.size () > 0)
682 {
683 QModelIndex index = rows[0];
684
685 QFileInfo info = m_file_system_model->fileInfo (index);
686 emit run_file_signal (info);
687 }
688 }
689
691 {
692 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
693 QModelIndexList rows = m->selectedRows ();
694 if (rows.size () > 0)
695 {
696 QModelIndex index = rows[0];
697
698 QFileInfo info = m_file_system_model->fileInfo (index);
699 QDir path = info.absoluteDir ();
700 QString old_name = info.fileName ();
701 bool ok;
702
703 QString new_name
704 = QInputDialog::getText (this, tr ("Rename file/directory"),
705 tr ("Rename file/directory:\n")
706 + old_name + tr ("\n to: "),
707 QLineEdit::Normal, old_name, &ok);
708 if (ok && new_name.length () > 0)
709 {
710 new_name = path.absolutePath () + '/' + new_name;
711 old_name = path.absolutePath () + '/' + old_name;
712 // editor: close old
713 emit file_remove_signal (old_name, new_name);
714 // Do the renaming
715 QFile f (old_name); // Must use QFile, not QDir (bug #56298)
716 bool st = f.rename (new_name);
717 if (! st)
718 QMessageBox::warning (this, tr ("Rename error"),
719 tr ("Could not rename file \"%1\" to \"%2\".").
720 arg (old_name).arg (new_name));
721 // editor: load new/old file depending on success
722 emit file_renamed_signal (st);
723 // Clear cache of file browser
724 m_file_system_model->revert ();
725 }
726 }
727
728 }
729
731 {
732 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
733 QModelIndexList rows = m->selectedRows ();
734
735 int file_cnt = rows.size ();
736 bool multiple_files = (file_cnt > 1);
737
738 for (auto it = rows.begin (); it != rows.end (); it++)
739 {
740 QModelIndex index = *it;
741
742 QFileInfo info = m_file_system_model->fileInfo (index);
743
744 QMessageBox::StandardButton dlg_answer;
745 if (multiple_files)
746 if (it == rows.begin ())
747 {
748 dlg_answer = QMessageBox::question (this,
749 tr ("Delete file/directory"),
750 tr ("Are you sure you want to delete all %1 selected files?\n").arg (file_cnt),
751 QMessageBox::Yes | QMessageBox::No);
752 if (dlg_answer != QMessageBox::Yes)
753 return;
754 }
755 else
756 dlg_answer = QMessageBox::Yes;
757 else
758 {
759 dlg_answer = QMessageBox::question (this,
760 tr ("Delete file/directory"),
761 tr ("Are you sure you want to delete\n")
762 + info.filePath (),
763 QMessageBox::Yes | QMessageBox::No);
764 }
765
766 if (dlg_answer)
767 {
768 if (info.isDir ())
769 {
770 // see if directory is empty
771 QDir path (info.absoluteFilePath ());
772 QList<QFileInfo> fileLst = path.entryInfoList (
773 QDir::Hidden | QDir::AllEntries |
774 QDir::NoDotAndDotDot | QDir::System);
775
776 if (fileLst.count () != 0)
777 QMessageBox::warning (this, tr ("Delete file/directory"),
778 tr ("Can not delete a directory that is not empty"));
779 else
780 m_file_system_model->rmdir (index);
781 }
782 else
783 {
784 // Close the file in the editor if open
785 emit file_remove_signal (info.filePath (), QString ());
786 // Remove the file.
787 bool st = m_file_system_model->remove (index);
788 if (! st)
789 {
790 QMessageBox::warning (this, tr ("Deletion error"),
791 tr ("Could not delete file \"%1\".").
792 arg (info.filePath ()));
793 // Reload the old file
794 emit file_renamed_signal (false);
795 }
796 }
797
798 m_file_system_model->revert ();
799
800 }
801 }
802 }
803
804 // Get the currently selected files/dirs and return their file info
805 // in a list.
807 {
808 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
809 QModelIndexList rows = m->selectedRows ();
810
811 QList<QFileInfo> infos;
812
813 for (auto it = rows.begin (); it != rows.end (); it++)
814 {
815 QModelIndex index = *it;
816
817 QFileInfo info = m_file_system_model->fileInfo (index);
818
819 if (info.exists () &&
820 ((dir & info.isDir ()) || (! dir && info.isFile ())))
821 infos.append (info);
822 }
823
824 return infos;
825 }
826
828 {
829 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
830 QModelIndexList rows = m->selectedRows ();
831
832 if (rows.size () > 0)
833 {
834 QModelIndex index = rows[0];
835
836 QFileInfo info = m_file_system_model->fileInfo (index);
837 QString parent_dir = info.filePath ();
838
839 process_new_file (parent_dir);
840 }
841 }
842
844 {
845 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
846 QModelIndexList rows = m->selectedRows ();
847
848 if (rows.size () > 0)
849 {
850 QModelIndex index = rows[0];
851
852 QFileInfo info = m_file_system_model->fileInfo (index);
853 QString parent_dir = info.filePath ();
854
855 process_new_dir (parent_dir);
856 }
857 }
858
860 {
862
863 if (infos.length () > 0 && infos.first ().isDir ())
864 process_set_current_dir (infos.first ().absoluteFilePath ());
865 }
866
867 void files_dock_widget::contextmenu_add_to_path (bool, bool rm, bool subdirs)
868 {
870
871 QStringList dir_list;
872
873 for (int i = 0; i < infos.length (); i++)
874 dir_list.append (infos.at (i).absoluteFilePath ());
875
876 if (infos.length () > 0)
877 emit modify_path_signal (dir_list, rm, subdirs);
878 }
879
881 {
882 contextmenu_add_to_path (true, false, true);
883 }
884
886 {
887 contextmenu_add_to_path (true, true, false);
888 }
889
891 {
892 contextmenu_add_to_path (true, true, true);
893 }
894
896 {
897 QItemSelectionModel *m = m_file_tree_view->selectionModel ();
898 QModelIndexList rows = m->selectedRows ();
899
900 if (rows.size () > 0)
901 {
902 QModelIndex index = rows[0];
903
904 QFileInfo info = m_file_system_model->fileInfo (index);
905
906 if (info.isDir ())
907 {
908 process_find_files (info.absoluteFilePath ());
909 }
910 }
911 }
912
914 {
915 // QSettings pointer is checked before emitting.
916
917 int size_idx = settings->value (global_icon_size).toInt ();
918 size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2
919
920 QStyle *st = style ();
921 int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);
922 m_navigation_tool_bar->setIconSize (QSize (icon_size, icon_size));
923
924 // filenames are always shown, other columns can be hidden by settings
925 for (int i = 0; i < 3; i++)
926 m_file_tree_view->setColumnHidden (i + 1,
927 ! settings->value (m_columns_shown_keys.at (i),false).toBool ());
928
929 QDir::Filters current_filter = m_file_system_model->filter ();
930 if (settings->value (m_columns_shown_keys.at (3), false).toBool ())
931 m_file_system_model->setFilter (current_filter | QDir::Hidden);
932 else
933 m_file_system_model->setFilter (current_filter & (~QDir::Hidden));
934
935 m_file_tree_view->setAlternatingRowColors
936 (settings->value (m_columns_shown_keys.at (4),true).toBool ());
938
939 // enable the buttons to sync octave/browser dir
940 // only if this is not done by default
942 = settings->value (fb_sync_octdir).toBool ();
945
946 // If m_sync_octave_dir is enabled, then we want the file browser to
947 // update to match the current working directory of the
948 // interpreter. We don't want to queue any signal to change the
949 // interpreter's current working directory. In this case, we just
950 // want the GUI to match the state of the interpreter.
951
954 }
955
957 {
959
960 if (dir.isEmpty ())
961 dir = QDir::homePath ();
962
964 }
965
967 {
968 // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
969 int opts = QFileDialog::ShowDirsOnly;
972 if (! settings->value (global_use_native_dialogs).toBool ())
973 opts |= QFileDialog::DontUseNativeDialog;
974
975 QString dir = QFileDialog::getExistingDirectory (this,
976 tr ("Set directory of file browser"),
977 m_file_system_model->rootPath (),
978 QFileDialog::Option (opts));
980 }
981
983 {
985 }
986
988 {
990 }
991
993 {
995 }
996
997 void files_dock_widget::process_new_file (const QString& parent_dir)
998 {
999 bool ok;
1000
1001 QString name = QInputDialog::getText (this, tr ("Create File"),
1002 tr ("Create file in\n", "String ends with \\n!") + parent_dir,
1003 QLineEdit::Normal,
1004 tr ("New File.txt"), &ok);
1005 if (ok && name.length () > 0)
1006 {
1007 name = parent_dir + '/' + name;
1008
1009 QFile file (name);
1010 file.open (QIODevice::WriteOnly);
1011 m_file_system_model->revert ();
1012 }
1013 }
1014
1015 void files_dock_widget::process_new_dir (const QString& parent_dir)
1016 {
1017 bool ok;
1018
1019 QString name = QInputDialog::getText (this, tr ("Create Directory"),
1020 tr ("Create folder in\n", "String ends with \\n!") + parent_dir,
1021 QLineEdit::Normal,
1022 tr ("New Directory"), &ok);
1023 if (ok && name.length () > 0)
1024 {
1025 QDir dir (parent_dir);
1026 dir.mkdir (name);
1027 m_file_system_model->revert ();
1028 }
1029 }
1030
1032 {
1033 emit displayed_directory_changed (dir);
1034 }
1035
1037 {
1038 emit find_files_signal (dir);
1039 }
1040
1042 {
1043 if (m_file_tree_view->hasFocus ())
1045 if (m_current_directory->hasFocus ())
1046 {
1047 QClipboard *clipboard = QApplication::clipboard ();
1048
1049 QLineEdit *edit = m_current_directory->lineEdit ();
1050 if (edit && edit->hasSelectedText ())
1051 {
1052 clipboard->setText (edit->selectedText ());
1053 }
1054 }
1055 }
1056
1058 {
1059 if (m_current_directory->hasFocus ())
1060 {
1061 QClipboard *clipboard = QApplication::clipboard ();
1062 QString str = clipboard->text ();
1063 QLineEdit *edit = m_current_directory->lineEdit ();
1064 if (edit && str.length () > 0)
1065 edit->insert (str);
1066 }
1067 }
1068
1070 {
1071 if (m_file_tree_view->hasFocus ())
1072 m_file_tree_view->selectAll ();
1073 if (m_current_directory->hasFocus ())
1074 {
1075 QLineEdit *edit = m_current_directory->lineEdit ();
1076 if (edit)
1077 {
1078 edit->selectAll ();
1079 }
1080 }
1081 }
1082}
void mousePressEvent(QMouseEvent *e)
~FileTreeViewer(void)=default
Base class for Octave interfaces that use Qt.
resource_manager & get_resource_manager(void)
void contextmenu_copy_selection(bool)
Context menu actions.
void contextmenu_rm_from_path_subdirs(bool)
Context menu actions.
QString m_octave_dir
The actual Octave directory.
void contextmenu_add_to_path_subdirs(bool)
Context menu actions.
void contextmenu_add_to_path(bool, bool rm=false, bool subdirs=false)
Context menu actions.
void process_new_dir(const QString &parent_name)
void do_sync_browser_directory(void)
Slot for handling the sync browser directory button in the toolbar.
void open_item_in_app(const QModelIndex &index)
void process_new_file(const QString &parent_name)
Process new file/directory actions.
void headercontextmenu_requested(const QPoint &pos)
void contextmenu_run(bool)
Context menu actions.
void open_file(const QString &fileName)
Emitted, whenever the user requested to open a file.
void open_any_signal(const QString &fileName)
Emitted, whenever the user requested to open an unknown type file.
void update_octave_directory(const QString &dir)
Set the internal variable that holds the actual octave variable.
void contextmenu_rm_from_path(bool)
Context menu actions.
void process_set_current_dir(const QString &parent_name)
Process setting current dir or find in files.
QList< QFileInfo > get_selected_items_info(bool)
Get currently selected QFileInfo object.
QTreeView * m_file_tree_view
The file system view.
void modify_path_signal(const QStringList &dir_list, bool rm, bool subdirs)
Emitted, when the path has to be modified.
void notice_settings(const gui_settings *settings)
Tells the widget to react on changed settings.
void contextmenu_load(bool)
Context menu actions.
void copyClipboard()
Inherited from octave_doc_widget.
void selectAll()
Inherited from octave_doc_widget.
QToolBar * m_navigation_tool_bar
Variables for the actions.
void change_directory_up(void)
Slot for handling the up-directory button in the toolbar.
void run_file_signal(const QFileInfo &info)
Emitted, whenever the user requested to run a file.
void accept_directory_line_edit(void)
Accepts user input a the line edit for the current directory.
void popdownmenu_newdir(bool)
Popdown menu options.
void contextmenu_newdir(bool)
Context menu actions.
void display_directory(const QString &dir, bool set_octave_dir=true)
set a new directory or open a file
void popdownmenu_search_dir(bool)
Popdown menu options.
void popdownmenu_home(bool)
Popdown menu options.
void contextmenu_open(bool)
Context menu actions.
files_dock_widget(QWidget *parent, base_qobject &oct_qobj)
void contextmenu_open_in_editor(bool)
Context menu actions.
void item_double_clicked(const QModelIndex &index)
Slot for handling a change in directory via double click.
bool m_sync_octave_dir
Flag if syncing with Octave.
void pasteClipboard()
Inherited from octave_doc_widget.
void contextmenu_newfile(bool)
Context menu actions.
QFileSystemModel * m_file_system_model
The file system model.
void contextmenu_requested(const QPoint &pos)
Context menu wanted.
void do_sync_octave_directory(void)
Slot for handling the sync octave directory button in the toolbar.
void file_remove_signal(const QString &old_name, const QString &new_name)
Emitted, whenever the user removes or renames a file.
void popdownmenu_findfiles(bool)
Popdown menu options.
QComboBox * m_current_directory
The file system view.
void process_find_files(const QString &dir_name)
void contextmenu_rename(bool)
Context menu actions.
QList< QVariant > m_columns_shown_defs
void find_files_signal(const QString &startdir)
Emitted, whenever wants to search for a file .
void contextmenu_setcurrentdir(bool)
Context menu actions.
void contextmenu_delete(bool)
Context menu actions.
void load_file_signal(const QString &fileName)
Emitted, whenever the user requested to load a file in the text editor.
void popdownmenu_newfile(bool)
Popdown menu options.
void set_current_directory(const QString &dir)
Sets the current directory being displayed.
void file_renamed_signal(bool)
Emitted, when a file or directory is renamed.
void contextmenu_findfiles(bool)
Context menu actions.
void contextmenu_open_in_app(bool)
Context menu actions.
void displayed_directory_changed(const QString &dir)
Emitted, whenever the currently displayed directory changed.
void set_title(const QString &)
void make_window(bool widget_was_dragged=false)
virtual void save_settings(void)
gui_settings * get_settings(void) const
QIcon icon(const QString &icon_name, bool fallback=true)
static std::string get_home_directory(void)
Definition: oct-env.cc:145
void warning(const char *fmt,...)
Definition: error.cc:1055
QString path
QString name
const gui_pref fb_mru_list("filesdockwidget/mru_dir_list", QVariant(QStringList()))
const gui_pref fb_column_state("filesdockwidget/column_state", QVariant())
const gui_pref fb_show_date("filesdockwidget/showLastModified", QVariant(false))
const gui_pref fb_sync_octdir("filesdockwidget/sync_octave_directory", QVariant(true))
const gui_pref fb_sort_order("filesdockwidget/sort_files_by_order", QVariant(Qt::AscendingOrder))
const gui_pref fb_sort_column("filesdockwidget/sort_files_by_column", QVariant(0))
const gui_pref fb_show_type("filesdockwidget/showFileType", QVariant(false))
const gui_pref fb_show_hidden("filesdockwidget/showHiddenFiles", QVariant(false))
const gui_pref fb_startup_dir("filesdockwidget/startup_dir", QVariant(QString()))
const gui_pref fb_show_size("filesdockwidget/showFileSize", QVariant(false))
const gui_pref fb_txt_file_ext("filesdockwidget/txt_file_extensions", QVariant("m;c;cc;cpp;h;txt"))
const gui_pref fb_restore_last_dir("filesdockwidget/restore_last_dir", QVariant(false))
const gui_pref fb_show_altcol("filesdockwidget/useAlternatingRowColors", QVariant(true))
const QStyle::PixelMetric global_icon_sizes[3]
const gui_pref global_use_native_dialogs("use_native_file_dialogs", QVariant(true))
const gui_pref global_icon_size("toolbar_icon_size", QVariant(0))
QString fromStdString(const std::string &s)
static double f(double k, double l_nu, double c_pm)
Definition: randpoisson.cc:118
const QString key
const QVariant def