2017-11-04 07:03:53 +01:00
|
|
|
/***********************************************************************
|
|
|
|
* ffiledialog.cpp - Widget FFileDialog (a file chooser dialog) *
|
|
|
|
* *
|
2020-07-08 21:32:47 +02:00
|
|
|
* This file is part of the FINAL CUT widget toolkit *
|
2017-11-04 07:03:53 +01:00
|
|
|
* *
|
2020-01-03 01:33:18 +01:00
|
|
|
* Copyright 2014-2020 Markus Gans *
|
2017-11-04 07:03:53 +01:00
|
|
|
* *
|
2020-07-08 21:32:47 +02:00
|
|
|
* FINAL CUT is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU Lesser General Public License as *
|
|
|
|
* published by the Free Software Foundation; either version 3 of *
|
2017-11-04 07:03:53 +01:00
|
|
|
* the License, or (at your option) any later version. *
|
|
|
|
* *
|
2020-07-08 21:32:47 +02:00
|
|
|
* FINAL CUT is distributed in the hope that it will be useful, but *
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
2017-11-04 07:03:53 +01:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU Lesser General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
|
|
* License along with this program. If not, see *
|
|
|
|
* <http://www.gnu.org/licenses/>. *
|
|
|
|
***********************************************************************/
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-12-30 04:24:46 +01:00
|
|
|
#if defined(__CYGWIN__)
|
2019-08-18 02:04:44 +02:00
|
|
|
#undef __STRICT_ANSI__ // need for strdup
|
2018-12-30 04:24:46 +01:00
|
|
|
#include <strings.h> // need for strcasecmp
|
|
|
|
#endif
|
|
|
|
|
2020-10-08 12:09:48 +02:00
|
|
|
#include <array>
|
2017-09-11 03:06:02 +02:00
|
|
|
#include <vector>
|
|
|
|
|
2019-07-21 23:31:21 +02:00
|
|
|
#include "final/fevent.h"
|
2019-08-18 02:04:44 +02:00
|
|
|
#include "final/fsystem.h"
|
2017-09-17 21:32:46 +02:00
|
|
|
#include "final/ffiledialog.h"
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-09-20 23:59:01 +02:00
|
|
|
namespace finalcut
|
|
|
|
{
|
2017-09-11 03:06:02 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// non-member functions
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2020-05-02 00:07:35 +02:00
|
|
|
bool sortByName ( const FFileDialog::FDirEntry& lhs
|
|
|
|
, const FFileDialog::FDirEntry& rhs )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
|
|
|
// lhs < rhs
|
2020-04-19 20:38:52 +02:00
|
|
|
return bool( strcasecmp(lhs.name.c_str(), rhs.name.c_str()) < 0 );
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2020-05-02 00:07:35 +02:00
|
|
|
bool sortDirFirst ( const FFileDialog::FDirEntry& lhs
|
|
|
|
, const FFileDialog::FDirEntry& rhs )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
|
|
|
// sort directories first
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( lhs.directory && ! rhs.directory )
|
2015-05-23 13:35:12 +02:00
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-12 09:11:22 +01:00
|
|
|
//----------------------------------------------------------------------
|
2020-10-04 00:59:21 +02:00
|
|
|
FString fileChooser ( FWidget* parent
|
|
|
|
, const FString& dirname
|
|
|
|
, const FString& filter
|
|
|
|
, FFileDialog::DialogType type )
|
2019-01-12 09:11:22 +01:00
|
|
|
{
|
2019-08-25 22:16:00 +02:00
|
|
|
FString ret{};
|
2020-05-02 00:07:35 +02:00
|
|
|
FString path{dirname};
|
|
|
|
FString file_filter{filter};
|
2019-01-12 09:11:22 +01:00
|
|
|
|
|
|
|
if ( path.isNull() || path.isEmpty() )
|
|
|
|
{
|
2019-08-25 22:16:00 +02:00
|
|
|
path.setString(FFileDialog::getHomeDir());
|
2019-01-12 09:11:22 +01:00
|
|
|
|
|
|
|
if ( path.isNull() || path.isEmpty() )
|
2019-08-25 22:16:00 +02:00
|
|
|
path.setString("/");
|
2019-01-12 09:11:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( file_filter.isNull() || file_filter.isEmpty() )
|
2019-08-25 22:16:00 +02:00
|
|
|
file_filter.setString("*");
|
2019-01-12 09:11:22 +01:00
|
|
|
|
|
|
|
FFileDialog fileopen ( path
|
|
|
|
, file_filter
|
|
|
|
, type
|
|
|
|
, parent );
|
|
|
|
|
|
|
|
if ( fileopen.exec() == FDialog::Accept )
|
|
|
|
ret = fileopen.getPath() + fileopen.getSelectedFile();
|
|
|
|
else
|
2020-05-02 00:07:35 +02:00
|
|
|
ret = FString{};
|
2019-01-12 09:11:22 +01:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-08-18 21:35:36 +02:00
|
|
|
// static class attributes
|
2019-08-25 22:16:00 +02:00
|
|
|
FSystem* FFileDialog::fsystem{nullptr};
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2019-10-14 01:44:24 +02:00
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
// class FFileDialog
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
|
|
// constructors and destructor
|
|
|
|
//----------------------------------------------------------------------
|
2016-10-01 23:18:49 +02:00
|
|
|
FFileDialog::FFileDialog (FWidget* parent)
|
2020-05-24 23:55:08 +02:00
|
|
|
: FDialog{parent}
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2015-09-22 04:18:20 +02:00
|
|
|
FFileDialog::FFileDialog (const FFileDialog& fdlg)
|
2020-05-24 23:55:08 +02:00
|
|
|
: FDialog{fdlg.getParentWidget()}
|
2015-09-22 04:18:20 +02:00
|
|
|
{
|
2018-12-03 03:22:36 +01:00
|
|
|
if ( fdlg.directory )
|
|
|
|
setPath(fdlg.directory);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2015-09-22 04:18:20 +02:00
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
FFileDialog::FFileDialog ( const FString& dirname
|
|
|
|
, const FString& filter
|
|
|
|
, DialogType type
|
|
|
|
, FWidget* parent )
|
2020-05-24 23:55:08 +02:00
|
|
|
: FDialog{parent}
|
|
|
|
, filter_pattern{filter}
|
|
|
|
, dlg_type{type}
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-03-21 00:02:43 +01:00
|
|
|
if ( ! dirname.isNull() )
|
2015-05-23 13:35:12 +02:00
|
|
|
setPath(dirname);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
init();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
FFileDialog::~FFileDialog() // destructor
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// public methods of FFileDialog
|
2015-05-23 13:35:12 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
FFileDialog& FFileDialog::operator = (const FFileDialog& fdlg)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( &fdlg == this )
|
2016-08-21 21:27:44 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
return *this;
|
2016-08-21 21:27:44 +02:00
|
|
|
}
|
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
clear();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( fdlg.getParentWidget() )
|
|
|
|
fdlg.getParentWidget()->addChild (this);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
directory = fdlg.directory;
|
|
|
|
filter_pattern = fdlg.filter_pattern;
|
|
|
|
dlg_type = fdlg.dlg_type;
|
|
|
|
show_hidden = fdlg.show_hidden;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( directory )
|
|
|
|
setPath(directory);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
init();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2020-10-04 00:59:21 +02:00
|
|
|
FString FFileDialog::getSelectedFile() const
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2020-10-04 02:55:15 +02:00
|
|
|
const auto n = uLong(filebrowser.currentItem() - 1);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( dir_entries[n].directory )
|
2020-05-02 00:07:35 +02:00
|
|
|
return FString{""};
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2020-05-02 00:07:35 +02:00
|
|
|
return FString{dir_entries[n].name};
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FFileDialog::setPath (const FString& dir)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2020-10-25 01:21:45 +02:00
|
|
|
const auto& dirname = dir.c_str();
|
2020-10-08 05:55:32 +02:00
|
|
|
std::array<char, MAXPATHLEN> resolved_path{};
|
2019-08-25 22:16:00 +02:00
|
|
|
FString r_dir{};
|
|
|
|
struct stat sb{};
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( stat(dirname, &sb) != 0 )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
directory = '/';
|
|
|
|
return;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2020-04-19 20:38:52 +02:00
|
|
|
if ( S_ISLNK(sb.st_mode) && lstat(dirname, &sb) != 0 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2020-04-19 20:38:52 +02:00
|
|
|
directory = '/';
|
|
|
|
return;
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ! S_ISDIR(sb.st_mode) )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
directory = '/';
|
|
|
|
return;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
|
2020-10-08 05:55:32 +02:00
|
|
|
if ( fsystem && fsystem->realpath(dir.c_str(), resolved_path.data()) != nullptr )
|
|
|
|
r_dir.setString(resolved_path.data());
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2019-08-25 22:16:00 +02:00
|
|
|
r_dir.setString(dir);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-08-27 09:50:30 +02:00
|
|
|
if ( r_dir[r_dir.getLength() - 1] != '/' )
|
2016-11-02 00:37:58 +01:00
|
|
|
directory = r_dir + "/";
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
directory = r_dir;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FFileDialog::setFilter (const FString& filter)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
filter_pattern = filter;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2018-12-22 23:50:10 +01:00
|
|
|
bool FFileDialog::setShowHiddenFiles (bool enable)
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-12-22 23:50:10 +01:00
|
|
|
if ( show_hidden == enable )
|
2016-11-02 00:37:58 +01:00
|
|
|
return show_hidden;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-12-22 23:50:10 +01:00
|
|
|
show_hidden = enable;
|
2016-11-02 00:37:58 +01:00
|
|
|
readDir();
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.redraw();
|
2016-11-02 00:37:58 +01:00
|
|
|
return show_hidden;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FFileDialog::onKeyPress (FKeyEvent* ev)
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ! isEnabled() )
|
|
|
|
return;
|
2016-10-17 08:44:38 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
FDialog::onKeyPress (ev);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-10-03 22:23:55 +02:00
|
|
|
if ( ! filebrowser.hasFocus() )
|
2016-11-02 00:37:58 +01:00
|
|
|
return;
|
|
|
|
|
2020-02-02 22:34:27 +01:00
|
|
|
const FKey key = ev->key();
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
switch ( key )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
case fc::Fkey_erase:
|
|
|
|
case fc::Fkey_backspace:
|
|
|
|
changeDir("..");
|
|
|
|
ev->accept();
|
|
|
|
break;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
default:
|
|
|
|
break;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2020-10-04 00:59:21 +02:00
|
|
|
FString FFileDialog::fileOpenChooser ( FWidget* parent
|
|
|
|
, const FString& dirname
|
|
|
|
, const FString& filter )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2019-01-12 09:11:22 +01:00
|
|
|
return fileChooser (parent, dirname, filter, FFileDialog::Open);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2020-10-04 00:59:21 +02:00
|
|
|
FString FFileDialog::fileSaveChooser ( FWidget* parent
|
|
|
|
, const FString& dirname
|
|
|
|
, const FString& filter )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2019-01-12 09:11:22 +01:00
|
|
|
return fileChooser (parent, dirname, filter, FFileDialog::Save);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// protected methods of FFileDialog
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FFileDialog::adjustSize()
|
|
|
|
{
|
2020-04-13 12:40:11 +02:00
|
|
|
std::size_t max_width{};
|
|
|
|
std::size_t max_height{};
|
2020-02-02 22:34:27 +01:00
|
|
|
const auto& root_widget = getRootWidget();
|
2016-08-21 21:27:44 +02:00
|
|
|
|
|
|
|
if ( root_widget )
|
|
|
|
{
|
|
|
|
max_width = root_widget->getClientWidth();
|
|
|
|
max_height = root_widget->getClientHeight();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-07-03 16:56:32 +02:00
|
|
|
// fallback to xterm default size
|
2016-08-21 21:27:44 +02:00
|
|
|
max_width = 80;
|
|
|
|
max_height = 24;
|
|
|
|
}
|
|
|
|
|
2019-08-25 22:16:00 +02:00
|
|
|
std::size_t h = max_height - 6;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
if ( h < 15 ) // minimum
|
|
|
|
h = 15;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
if ( h > 30 ) // maximum
|
|
|
|
h = 30;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2015-05-23 13:35:12 +02:00
|
|
|
setHeight (h, false);
|
2020-02-02 22:34:27 +01:00
|
|
|
const int X = 1 + int((max_width - getWidth()) / 2);
|
|
|
|
const int Y = 1 + int((max_height - getHeight()) / 3);
|
2020-05-02 00:07:35 +02:00
|
|
|
setPos(FPoint{X, Y}, false);
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.setHeight (h - 8, false);
|
2019-05-17 15:48:09 +02:00
|
|
|
hidden_check.setY (int(h) - 4, false);
|
|
|
|
cancel_btn.setY (int(h) - 4, false);
|
|
|
|
open_btn.setY (int(h) - 4, false);
|
2015-05-23 13:35:12 +02:00
|
|
|
FDialog::adjustSize();
|
|
|
|
printPath(directory);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
// private methods of FFileDialog
|
2015-09-22 04:18:20 +02:00
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FFileDialog::init()
|
2015-09-22 04:18:20 +02:00
|
|
|
{
|
2018-12-26 23:41:49 +01:00
|
|
|
static constexpr std::size_t w = 42;
|
|
|
|
static constexpr std::size_t h = 15;
|
2020-04-13 12:40:11 +02:00
|
|
|
int x{};
|
|
|
|
int y{};
|
2019-08-18 02:04:44 +02:00
|
|
|
|
|
|
|
if ( ! fsystem )
|
|
|
|
fsystem = FTerm::getFSystem();
|
2017-07-12 01:16:57 +02:00
|
|
|
|
2020-05-02 00:07:35 +02:00
|
|
|
setGeometry(FPoint{1, 1}, FSize{w, h}, false);
|
2020-02-02 22:34:27 +01:00
|
|
|
const auto& parent_widget = getParentWidget();
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
if ( parent_widget )
|
2016-10-17 08:44:38 +02:00
|
|
|
{
|
2017-08-27 09:50:30 +02:00
|
|
|
x = 1 + int((parent_widget->getWidth() - w) / 2);
|
|
|
|
y = 1 + int((parent_widget->getHeight() - h) / 3);
|
2016-10-17 08:44:38 +02:00
|
|
|
}
|
2015-09-22 04:18:20 +02:00
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
x = y = 1;
|
2016-08-21 21:27:44 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( dlg_type == FFileDialog::Save )
|
|
|
|
FDialog::setText("Save file");
|
|
|
|
else
|
|
|
|
FDialog::setText("Open file");
|
2016-08-21 21:27:44 +02:00
|
|
|
|
2020-05-02 00:07:35 +02:00
|
|
|
widgetSettings (FPoint{x, y}); // Create widgets
|
2018-01-31 23:37:03 +01:00
|
|
|
initCallbacks();
|
|
|
|
setModal();
|
|
|
|
readDir();
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2019-01-21 03:42:18 +01:00
|
|
|
inline void FFileDialog::widgetSettings (const FPoint& pos)
|
2018-01-31 23:37:03 +01:00
|
|
|
{
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.setLabelText ("File&name");
|
|
|
|
filename.setText (filter_pattern);
|
2020-05-02 00:07:35 +02:00
|
|
|
filename.setGeometry (FPoint{11, 1}, FSize{28, 1});
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.setFocus();
|
2015-09-22 04:18:20 +02:00
|
|
|
|
2020-05-02 00:07:35 +02:00
|
|
|
filebrowser.setGeometry (FPoint{2, 3}, FSize{38, 6});
|
2018-10-03 22:23:55 +02:00
|
|
|
printPath (directory);
|
2015-09-22 04:18:20 +02:00
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
hidden_check.setText ("&hidden files");
|
2020-05-02 00:07:35 +02:00
|
|
|
hidden_check.setGeometry (FPoint{2, 10}, FSize{16, 1});
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
cancel_btn.setText ("&Cancel");
|
2020-05-02 00:07:35 +02:00
|
|
|
cancel_btn.setGeometry(FPoint{19, 10}, FSize{9, 1});
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2018-10-03 22:23:55 +02:00
|
|
|
if ( dlg_type == FFileDialog::Save )
|
2019-05-17 15:48:09 +02:00
|
|
|
open_btn.setText ("&Save");
|
2018-10-03 22:23:55 +02:00
|
|
|
else
|
2019-05-17 15:48:09 +02:00
|
|
|
open_btn.setText ("&Open");
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2020-05-02 00:07:35 +02:00
|
|
|
open_btn.setGeometry(FPoint{30, 10}, FSize{9, 1});
|
2019-01-27 22:19:33 +01:00
|
|
|
setGeometry (pos, getSize());
|
2018-01-31 23:37:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FFileDialog::initCallbacks()
|
|
|
|
{
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.addCallback
|
2016-11-02 00:37:58 +01:00
|
|
|
(
|
|
|
|
"activate",
|
2020-08-11 23:04:46 +02:00
|
|
|
this, &FFileDialog::cb_processActivate
|
2016-11-02 00:37:58 +01:00
|
|
|
);
|
2016-07-10 00:23:39 +02:00
|
|
|
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.addCallback
|
2016-11-02 00:37:58 +01:00
|
|
|
(
|
|
|
|
"row-changed",
|
2020-08-11 23:04:46 +02:00
|
|
|
this, &FFileDialog::cb_processRowChanged
|
2016-11-02 00:37:58 +01:00
|
|
|
);
|
2015-09-20 05:44:50 +02:00
|
|
|
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.addCallback
|
2016-11-02 00:37:58 +01:00
|
|
|
(
|
|
|
|
"clicked",
|
2020-08-11 23:04:46 +02:00
|
|
|
this, &FFileDialog::cb_processClicked
|
2016-11-02 00:37:58 +01:00
|
|
|
);
|
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
hidden_check.addCallback
|
2016-11-02 00:37:58 +01:00
|
|
|
(
|
|
|
|
"toggled",
|
2020-08-11 23:04:46 +02:00
|
|
|
this, &FFileDialog::cb_processShowHidden
|
2016-11-02 00:37:58 +01:00
|
|
|
);
|
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
cancel_btn.addCallback
|
2016-11-02 00:37:58 +01:00
|
|
|
(
|
|
|
|
"clicked",
|
2020-08-11 23:04:46 +02:00
|
|
|
this, &FFileDialog::cb_processCancel
|
2016-11-02 00:37:58 +01:00
|
|
|
);
|
|
|
|
|
2019-05-17 15:48:09 +02:00
|
|
|
open_btn.addCallback
|
2016-11-02 00:37:58 +01:00
|
|
|
(
|
|
|
|
"clicked",
|
2020-08-11 23:04:46 +02:00
|
|
|
this, &FFileDialog::cb_processOpen
|
2016-11-02 00:37:58 +01:00
|
|
|
);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2020-07-12 15:25:21 +02:00
|
|
|
inline bool FFileDialog::patternMatch ( const char* const pattern
|
|
|
|
, const char fname[] ) const
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2020-10-08 05:55:32 +02:00
|
|
|
std::array<char, 128> search{};
|
2016-11-02 00:37:58 +01:00
|
|
|
|
|
|
|
if ( show_hidden && fname[0] == '.' && fname[1] != '\0' ) // hidden files
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
search[0] = '.';
|
|
|
|
search[1] = '\0';
|
2020-10-08 05:55:32 +02:00
|
|
|
std::strncat(search.data(), pattern, search.size() - std::strlen(search.data()) - 1);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
else
|
2020-10-08 12:09:48 +02:00
|
|
|
std::strncpy(search.data(), pattern, search.size() - 1);
|
2018-09-16 19:33:40 +02:00
|
|
|
|
2020-10-08 05:55:32 +02:00
|
|
|
search[search.size() - 1] = '\0';
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2020-10-08 05:55:32 +02:00
|
|
|
if ( fnmatch (search.data(), fname, FNM_PERIOD) == 0 )
|
2016-11-02 00:37:58 +01:00
|
|
|
return true;
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
return false;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2016-11-02 00:37:58 +01:00
|
|
|
void FFileDialog::clear()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( dir_entries.empty() )
|
|
|
|
return;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
dir_entries.clear();
|
2019-04-27 01:23:30 +02:00
|
|
|
dir_entries.shrink_to_fit();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2019-10-05 23:20:07 +02:00
|
|
|
sInt64 FFileDialog::numOfDirs()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( dir_entries.empty() )
|
|
|
|
return 0;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2020-02-02 22:34:27 +01:00
|
|
|
const sInt64 n = std::count_if ( std::begin(dir_entries)
|
|
|
|
, std::end(dir_entries)
|
2020-05-02 00:07:35 +02:00
|
|
|
, [] (const FDirEntry& entry)
|
2020-02-02 22:34:27 +01:00
|
|
|
{
|
|
|
|
return entry.directory
|
2020-04-19 20:38:52 +02:00
|
|
|
&& std::strcmp(entry.name.c_str(), ".") != 0;
|
2020-02-02 22:34:27 +01:00
|
|
|
}
|
|
|
|
);
|
2016-11-02 00:37:58 +01:00
|
|
|
return n;
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FFileDialog::sortDir()
|
|
|
|
{
|
2020-01-03 01:33:18 +01:00
|
|
|
sInt64 start{0};
|
2017-12-17 01:06:53 +01:00
|
|
|
|
2020-04-19 20:38:52 +02:00
|
|
|
if ( std::strcmp((*dir_entries.begin()).name.c_str(), "..") == 0 )
|
2017-12-17 01:06:53 +01:00
|
|
|
start = 1;
|
|
|
|
|
2020-02-02 22:34:27 +01:00
|
|
|
const sInt64 dir_num = numOfDirs();
|
2017-12-17 01:06:53 +01:00
|
|
|
// directories first
|
|
|
|
std::sort ( dir_entries.begin() + start
|
|
|
|
, dir_entries.end()
|
|
|
|
, sortDirFirst );
|
|
|
|
// sort directories by name
|
|
|
|
std::sort ( dir_entries.begin() + start
|
|
|
|
, dir_entries.begin() + dir_num
|
|
|
|
, sortByName );
|
|
|
|
// sort files by name
|
|
|
|
std::sort ( dir_entries.begin() + dir_num
|
|
|
|
, dir_entries.end()
|
|
|
|
, sortByName );
|
|
|
|
}
|
|
|
|
|
2018-01-30 00:11:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FFileDialog::readDir()
|
|
|
|
{
|
2020-10-25 01:21:45 +02:00
|
|
|
const auto& dir = directory.c_str();
|
2018-01-30 00:11:58 +01:00
|
|
|
directory_stream = opendir(dir);
|
|
|
|
|
|
|
|
if ( ! directory_stream )
|
|
|
|
{
|
|
|
|
FMessageBox::error (this, "Can't open directory\n" + directory);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
clear();
|
|
|
|
|
|
|
|
while ( true )
|
|
|
|
{
|
|
|
|
errno = 0;
|
2020-04-20 01:01:20 +02:00
|
|
|
const struct dirent* next = readdir(directory_stream);
|
2018-01-30 00:11:58 +01:00
|
|
|
|
|
|
|
if ( next )
|
|
|
|
{
|
|
|
|
// Continue if name = "." (current directory)
|
|
|
|
if ( next->d_name[0] == '.' && next->d_name[1] == '\0' )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip hidden entries
|
|
|
|
if ( ! show_hidden
|
|
|
|
&& next->d_name[0] == '.'
|
|
|
|
&& next->d_name[1] != '\0'
|
|
|
|
&& next->d_name[1] != '.' )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip ".." for the root directory
|
|
|
|
if ( dir[0] == '/' && dir[1] == '\0'
|
|
|
|
&& std::strcmp(next->d_name, "..") == 0 )
|
|
|
|
continue;
|
|
|
|
|
2018-01-31 23:37:03 +01:00
|
|
|
getEntry(dir, next);
|
2018-01-30 00:11:58 +01:00
|
|
|
}
|
|
|
|
else if ( errno != 0 )
|
|
|
|
{
|
|
|
|
FMessageBox::error (this, "Reading directory\n" + directory);
|
|
|
|
|
|
|
|
if ( errno == EOVERFLOW ) // Value too large to be stored in data type
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
} // end while
|
|
|
|
|
|
|
|
if ( closedir(directory_stream) != 0 )
|
|
|
|
{
|
|
|
|
FMessageBox::error (this, "Closing directory\n" + directory);
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
|
|
|
|
sortDir();
|
|
|
|
|
|
|
|
// Insert directory entries into the list
|
|
|
|
dirEntriesToList();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2020-04-13 12:40:11 +02:00
|
|
|
void FFileDialog::getEntry (const char* const dir, const struct dirent* d_entry)
|
2018-01-30 00:11:58 +01:00
|
|
|
{
|
2020-10-25 01:21:45 +02:00
|
|
|
const auto& filter = filter_pattern.c_str();
|
2020-05-02 00:07:35 +02:00
|
|
|
FDirEntry entry{};
|
2018-01-30 00:11:58 +01:00
|
|
|
|
2020-04-19 20:38:52 +02:00
|
|
|
entry.name = d_entry->d_name;
|
2018-01-30 00:11:58 +01:00
|
|
|
|
|
|
|
#if defined _DIRENT_HAVE_D_TYPE || defined HAVE_STRUCT_DIRENT_D_TYPE
|
|
|
|
entry.fifo = (d_entry->d_type & DT_FIFO) == DT_FIFO;
|
|
|
|
entry.character_device = (d_entry->d_type & DT_CHR ) == DT_CHR;
|
|
|
|
entry.directory = (d_entry->d_type & DT_DIR ) == DT_DIR;
|
|
|
|
entry.block_device = (d_entry->d_type & DT_BLK ) == DT_BLK;
|
|
|
|
entry.regular_file = (d_entry->d_type & DT_REG ) == DT_REG;
|
|
|
|
entry.symbolic_link = (d_entry->d_type & DT_LNK ) == DT_LNK;
|
|
|
|
entry.socket = (d_entry->d_type & DT_SOCK) == DT_SOCK;
|
|
|
|
#else
|
2019-08-25 22:16:00 +02:00
|
|
|
struct stat s{};
|
2020-04-19 20:57:28 +02:00
|
|
|
stat (entry.name.c_str(), &s);
|
2018-01-30 00:11:58 +01:00
|
|
|
entry.fifo = S_ISFIFO (s.st_mode);
|
|
|
|
entry.character_device = S_ISCHR (s.st_mode);
|
|
|
|
entry.directory = S_ISDIR (s.st_mode);
|
|
|
|
entry.block_device = S_ISBLK (s.st_mode);
|
|
|
|
entry.regular_file = S_ISREG (s.st_mode);
|
|
|
|
entry.symbolic_link = S_ISLNK (s.st_mode);
|
|
|
|
entry.socket = S_ISSOCK (s.st_mode);
|
|
|
|
#endif
|
|
|
|
|
2018-01-31 23:37:03 +01:00
|
|
|
followSymLink (dir, entry);
|
2018-01-30 00:11:58 +01:00
|
|
|
|
|
|
|
if ( entry.directory )
|
|
|
|
dir_entries.push_back (entry);
|
2020-07-12 15:25:21 +02:00
|
|
|
else if ( patternMatch(filter, entry.name.c_str()) )
|
2018-01-30 00:11:58 +01:00
|
|
|
dir_entries.push_back (entry);
|
|
|
|
else
|
2020-04-19 20:38:52 +02:00
|
|
|
entry.name.clear();
|
2018-01-30 00:11:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2020-07-12 15:25:21 +02:00
|
|
|
void FFileDialog::followSymLink (const char* const dir, FDirEntry& entry) const
|
2018-01-30 00:11:58 +01:00
|
|
|
{
|
|
|
|
if ( ! entry.symbolic_link )
|
|
|
|
return; // No symbolic link
|
|
|
|
|
2020-10-08 05:55:32 +02:00
|
|
|
std::array<char, MAXPATHLEN> resolved_path{};
|
|
|
|
std::array<char, MAXPATHLEN> symLink{};
|
2019-08-25 22:16:00 +02:00
|
|
|
struct stat sb{};
|
2018-01-30 00:11:58 +01:00
|
|
|
|
2019-08-18 02:04:44 +02:00
|
|
|
if ( ! fsystem )
|
|
|
|
fsystem = FTerm::getFSystem();
|
|
|
|
|
2020-10-08 12:09:48 +02:00
|
|
|
std::strncpy (symLink.data(), dir, symLink.size() - 1);
|
2020-10-08 05:55:32 +02:00
|
|
|
symLink[symLink.size() - 1] = '\0';
|
|
|
|
std::strncat ( symLink.data()
|
2020-04-19 20:38:52 +02:00
|
|
|
, entry.name.c_str()
|
2020-10-08 05:55:32 +02:00
|
|
|
, symLink.size() - std::strlen(symLink.data()) - 1);
|
|
|
|
symLink[symLink.size() - 1] = '\0';
|
2018-01-30 00:11:58 +01:00
|
|
|
|
2020-10-08 05:55:32 +02:00
|
|
|
if ( fsystem->realpath(symLink.data(), resolved_path.data()) == nullptr )
|
2018-01-30 00:11:58 +01:00
|
|
|
return; // Cannot follow the symlink
|
|
|
|
|
2020-10-08 05:55:32 +02:00
|
|
|
if ( lstat(resolved_path.data(), &sb) == -1 )
|
2018-01-30 00:11:58 +01:00
|
|
|
return; // Cannot get file status
|
|
|
|
|
|
|
|
if ( S_ISDIR(sb.st_mode) )
|
|
|
|
entry.directory = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FFileDialog::dirEntriesToList()
|
|
|
|
{
|
|
|
|
// Fill list with directory entries
|
|
|
|
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.clear();
|
2018-01-30 00:11:58 +01:00
|
|
|
|
|
|
|
if ( dir_entries.empty() )
|
|
|
|
return;
|
|
|
|
|
2018-12-15 22:10:31 +01:00
|
|
|
for (auto&& entry : dir_entries)
|
2018-01-30 00:11:58 +01:00
|
|
|
{
|
2018-12-15 22:10:31 +01:00
|
|
|
if ( entry.directory )
|
2020-05-02 00:07:35 +02:00
|
|
|
filebrowser.insert(FString{entry.name}, fc::SquareBrackets);
|
2018-01-30 00:11:58 +01:00
|
|
|
else
|
2020-05-02 00:07:35 +02:00
|
|
|
filebrowser.insert(FString{entry.name});
|
2018-12-15 22:10:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FFileDialog::selectDirectoryEntry (const char* const name)
|
|
|
|
{
|
|
|
|
if ( dir_entries.empty() )
|
|
|
|
return;
|
2018-01-30 00:11:58 +01:00
|
|
|
|
2019-08-25 22:16:00 +02:00
|
|
|
std::size_t i{1};
|
2018-12-15 22:10:31 +01:00
|
|
|
|
|
|
|
for (auto&& entry : dir_entries)
|
|
|
|
{
|
2020-04-19 20:38:52 +02:00
|
|
|
if ( std::strcmp(entry.name.c_str(), name) == 0 )
|
2018-12-15 22:10:31 +01:00
|
|
|
{
|
|
|
|
filebrowser.setCurrentItem(i);
|
2020-05-02 00:07:35 +02:00
|
|
|
filename.setText(FString{name} + '/');
|
2018-12-15 22:10:31 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
2018-01-30 00:11:58 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
int FFileDialog::changeDir (const FString& dirname)
|
|
|
|
{
|
2020-05-02 00:07:35 +02:00
|
|
|
FString lastdir{directory};
|
|
|
|
FString newdir{dirname};
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2019-08-18 02:04:44 +02:00
|
|
|
if ( ! fsystem )
|
|
|
|
fsystem = FTerm::getFSystem();
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( newdir.includes('~') )
|
|
|
|
newdir = newdir.replace('~', getHomeDir());
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( newdir[0] == '/' )
|
|
|
|
setPath(newdir);
|
|
|
|
else
|
|
|
|
setPath(directory + newdir);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
switch ( readDir() )
|
|
|
|
{
|
|
|
|
case -1:
|
|
|
|
setPath(lastdir);
|
|
|
|
return -1;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
case -2:
|
|
|
|
setPath(lastdir);
|
|
|
|
readDir();
|
|
|
|
return -2;
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
case 0:
|
2020-05-02 00:07:35 +02:00
|
|
|
if ( newdir == FString{".."} )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2020-05-02 00:07:35 +02:00
|
|
|
if ( lastdir == FString{'/'} )
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.setText('/');
|
2018-12-15 22:10:31 +01:00
|
|
|
else
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2019-09-28 03:13:06 +02:00
|
|
|
auto baseName = basename(lastdir.c_str());
|
2018-12-15 22:10:31 +01:00
|
|
|
selectDirectoryEntry (baseName);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2020-05-02 00:07:35 +02:00
|
|
|
FString firstname{dir_entries[0].name};
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( dir_entries[0].directory )
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.setText(firstname + '/');
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.setText(firstname);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
printPath(directory);
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.redraw();
|
|
|
|
filebrowser.redraw();
|
2017-08-11 10:50:39 +02:00
|
|
|
// fall through
|
2016-11-02 00:37:58 +01:00
|
|
|
default:
|
|
|
|
return 0;
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
void FFileDialog::printPath (const FString& txt)
|
|
|
|
{
|
2018-12-26 23:41:49 +01:00
|
|
|
const auto& path = txt;
|
2019-09-28 03:13:06 +02:00
|
|
|
const std::size_t max_width = filebrowser.getWidth() - 4;
|
2020-02-02 22:34:27 +01:00
|
|
|
const std::size_t column_width = getColumnWidth(path);
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2019-09-28 03:13:06 +02:00
|
|
|
if ( column_width > max_width )
|
|
|
|
{
|
|
|
|
const std::size_t width = max_width - 2;
|
2020-02-02 22:34:27 +01:00
|
|
|
const std::size_t first = column_width + 1 - width;
|
2020-05-02 00:07:35 +02:00
|
|
|
const FString sub_str{getColumnSubString (path, first, width)};
|
2019-09-28 03:13:06 +02:00
|
|
|
filebrowser.setText(".." + sub_str);
|
|
|
|
}
|
2016-11-02 00:37:58 +01:00
|
|
|
else
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.setText(path);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-09-11 22:50:07 +02:00
|
|
|
//----------------------------------------------------------------------
|
2020-10-04 00:59:21 +02:00
|
|
|
FString FFileDialog::getHomeDir()
|
2017-09-11 22:50:07 +02:00
|
|
|
{
|
2019-08-25 22:16:00 +02:00
|
|
|
struct passwd pwd{};
|
|
|
|
struct passwd* pwd_ptr{};
|
2020-10-08 05:55:32 +02:00
|
|
|
std::array<char, 1024> buf{};
|
2017-09-11 22:50:07 +02:00
|
|
|
|
2019-08-18 02:04:44 +02:00
|
|
|
if ( ! fsystem )
|
|
|
|
fsystem = FTerm::getFSystem();
|
|
|
|
|
2020-02-02 22:34:27 +01:00
|
|
|
const uid_t euid = fsystem->geteuid();
|
2019-08-18 02:04:44 +02:00
|
|
|
|
2020-10-08 05:55:32 +02:00
|
|
|
if ( fsystem->getpwuid_r(euid, &pwd, buf.data(), buf.size(), &pwd_ptr) )
|
2020-05-02 00:07:35 +02:00
|
|
|
return FString{""};
|
2017-09-11 22:50:07 +02:00
|
|
|
else
|
2020-05-02 00:07:35 +02:00
|
|
|
return FString{pwd.pw_dir};
|
2017-09-11 22:50:07 +02:00
|
|
|
}
|
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2020-08-11 23:04:46 +02:00
|
|
|
void FFileDialog::cb_processActivate()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-10-03 22:23:55 +02:00
|
|
|
if ( filename.getText().includes('*')
|
|
|
|
|| filename.getText().includes('?') )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-10-03 22:23:55 +02:00
|
|
|
setFilter(filename.getText());
|
2016-11-02 00:37:58 +01:00
|
|
|
readDir();
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.redraw();
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2018-10-03 22:23:55 +02:00
|
|
|
else if ( filename.getText().getLength() == 0 )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
setFilter("*");
|
|
|
|
readDir();
|
2018-10-03 22:23:55 +02:00
|
|
|
filebrowser.redraw();
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2020-05-02 00:07:35 +02:00
|
|
|
else if ( filename.getText().trim() == FString{".."}
|
2018-10-03 22:23:55 +02:00
|
|
|
|| filename.getText().includes('/')
|
|
|
|
|| filename.getText().includes('~') )
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-10-03 22:23:55 +02:00
|
|
|
changeDir(filename.getText().trim());
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-08-25 22:16:00 +02:00
|
|
|
bool found{false};
|
2019-07-14 18:30:35 +02:00
|
|
|
const auto& input = filename.getText().trim();
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( ! dir_entries.empty() )
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2019-07-14 18:30:35 +02:00
|
|
|
found = std::any_of ( std::begin(dir_entries)
|
|
|
|
, std::end(dir_entries)
|
2020-05-02 00:07:35 +02:00
|
|
|
, [&input] (const FDirEntry& entry)
|
2019-07-14 18:30:35 +02:00
|
|
|
{
|
2020-05-02 00:07:35 +02:00
|
|
|
return ! entry.name.empty()
|
2019-07-14 18:30:35 +02:00
|
|
|
&& input
|
|
|
|
&& ! input.isNull()
|
2020-10-13 12:55:28 +02:00
|
|
|
&& std::strcmp(entry.name.c_str(), input.c_str()) == 0
|
2019-07-14 18:30:35 +02:00
|
|
|
&& entry.directory;
|
|
|
|
}
|
|
|
|
);
|
2016-11-02 00:37:58 +01:00
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
|
2019-07-14 18:30:35 +02:00
|
|
|
if ( found )
|
|
|
|
changeDir(input);
|
|
|
|
else
|
2016-11-02 00:37:58 +01:00
|
|
|
done (FDialog::Accept);
|
|
|
|
}
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2020-08-11 23:04:46 +02:00
|
|
|
void FFileDialog::cb_processRowChanged()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2018-10-14 06:25:33 +02:00
|
|
|
const std::size_t n = filebrowser.currentItem();
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
if ( n == 0 )
|
|
|
|
return;
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2020-05-02 00:07:35 +02:00
|
|
|
const auto& name = FString{dir_entries[n - 1].name};
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2018-10-14 06:25:33 +02:00
|
|
|
if ( dir_entries[n - 1].directory )
|
2019-08-25 22:16:00 +02:00
|
|
|
filename.setText(name + '/');
|
2015-05-23 13:35:12 +02:00
|
|
|
else
|
2019-08-25 22:16:00 +02:00
|
|
|
filename.setText(name);
|
2015-09-22 04:18:20 +02:00
|
|
|
|
2018-10-03 22:23:55 +02:00
|
|
|
filename.redraw();
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
2020-08-11 23:04:46 +02:00
|
|
|
void FFileDialog::cb_processClicked()
|
2015-05-23 13:35:12 +02:00
|
|
|
{
|
2020-10-04 02:55:15 +02:00
|
|
|
const auto n = uLong(filebrowser.currentItem() - 1);
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2017-12-17 01:06:53 +01:00
|
|
|
if ( dir_entries[n].directory )
|
2016-11-02 00:37:58 +01:00
|
|
|
changeDir(dir_entries[n].name);
|
|
|
|
else
|
|
|
|
done (FDialog::Accept);
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2020-08-11 23:04:46 +02:00
|
|
|
void FFileDialog::cb_processCancel()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
done (FDialog::Reject);
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2020-08-11 23:04:46 +02:00
|
|
|
void FFileDialog::cb_processOpen()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
|
|
|
done (FDialog::Accept);
|
|
|
|
}
|
2016-07-09 00:01:59 +02:00
|
|
|
|
2016-11-02 00:37:58 +01:00
|
|
|
//----------------------------------------------------------------------
|
2020-08-11 23:04:46 +02:00
|
|
|
void FFileDialog::cb_processShowHidden()
|
2016-11-02 00:37:58 +01:00
|
|
|
{
|
2018-11-20 21:11:04 +01:00
|
|
|
setShowHiddenFiles(! show_hidden);
|
2015-05-23 13:35:12 +02:00
|
|
|
}
|
2018-09-20 23:59:01 +02:00
|
|
|
|
|
|
|
} // namespace finalcut
|