mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Drag-and-drop for moving one file at a time works... badly.
This commit is contained in:
@@ -50,6 +50,13 @@ Path Path::parent() const
|
||||
return p;
|
||||
}
|
||||
|
||||
Path Path::concat(const std::string& s) const
|
||||
{
|
||||
Path p(*this);
|
||||
p.push_back(s);
|
||||
return p;
|
||||
}
|
||||
|
||||
std::string Path::to_str(const std::string sep) const
|
||||
{
|
||||
return join(*this, sep);
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
|
||||
public:
|
||||
Path parent() const;
|
||||
Path concat(const std::string& s) const;
|
||||
std::string to_str(const std::string sep = "/") const;
|
||||
};
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ MainWindowGen::MainWindowGen( wxWindow* parent, wxWindowID id, const wxString& t
|
||||
m_dataViewColumn3 = browserTree->AppendTextColumn( wxT("Mode"), 2, wxDATAVIEW_CELL_INERT, -1, static_cast<wxAlignment>(wxALIGN_LEFT), wxDATAVIEW_COL_RESIZABLE );
|
||||
fgSizer23->Add( browserTree, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
diskSpaceGauge = new wxGauge( browsePanel, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL );
|
||||
diskSpaceGauge = new wxGauge( browsePanel, wxID_ANY, 100, wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL|wxGA_SMOOTH );
|
||||
diskSpaceGauge->SetValue( 0 );
|
||||
fgSizer23->Add( diskSpaceGauge, 0, wxALL|wxEXPAND, 5 );
|
||||
|
||||
@@ -400,6 +400,9 @@ MainWindowGen::MainWindowGen( wxWindow* parent, wxWindowID id, const wxString& t
|
||||
browserMoreMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnBrowserRenameMenuItem ), this, browserRenameMenuItem->GetId());
|
||||
browserMoreMenu->Bind(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( MainWindowGen::OnBrowserDeleteMenuItem ), this, browserDeleteMenuItem->GetId());
|
||||
this->Connect( browserFormatTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBrowserFormatButton ) );
|
||||
browserTree->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, wxDataViewEventHandler( MainWindowGen::OnBrowserBeginDrag ), NULL, this );
|
||||
browserTree->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, wxDataViewEventHandler( MainWindowGen::OnBrowserDrop ), NULL, this );
|
||||
browserTree->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, wxDataViewEventHandler( MainWindowGen::OnBrowserDropPossible ), NULL, this );
|
||||
browserTree->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, wxDataViewEventHandler( MainWindowGen::OnBrowserFilenameChanged ), NULL, this );
|
||||
browserTree->Connect( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, wxDataViewEventHandler( MainWindowGen::OnBrowserDirectoryExpanding ), NULL, this );
|
||||
browserTree->Connect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( MainWindowGen::OnBrowserSelectionChanged ), NULL, this );
|
||||
@@ -433,6 +436,9 @@ MainWindowGen::~MainWindowGen()
|
||||
this->Disconnect( browserViewTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBrowserViewButton ) );
|
||||
this->Disconnect( browserSaveTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBrowserSaveButton ) );
|
||||
this->Disconnect( browserFormatTool->GetId(), wxEVT_COMMAND_TOOL_CLICKED, wxCommandEventHandler( MainWindowGen::OnBrowserFormatButton ) );
|
||||
browserTree->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG, wxDataViewEventHandler( MainWindowGen::OnBrowserBeginDrag ), NULL, this );
|
||||
browserTree->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_DROP, wxDataViewEventHandler( MainWindowGen::OnBrowserDrop ), NULL, this );
|
||||
browserTree->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE, wxDataViewEventHandler( MainWindowGen::OnBrowserDropPossible ), NULL, this );
|
||||
browserTree->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, wxDataViewEventHandler( MainWindowGen::OnBrowserFilenameChanged ), NULL, this );
|
||||
browserTree->Disconnect( wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, wxDataViewEventHandler( MainWindowGen::OnBrowserDirectoryExpanding ), NULL, this );
|
||||
browserTree->Disconnect( wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, wxDataViewEventHandler( MainWindowGen::OnBrowserSelectionChanged ), NULL, this );
|
||||
|
||||
@@ -2500,11 +2500,14 @@
|
||||
<property name="pos"></property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxDV_SINGLE</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="subclass"></property>
|
||||
<property name="tooltip"></property>
|
||||
<property name="window_extra_style"></property>
|
||||
<property name="window_name"></property>
|
||||
<property name="window_style"></property>
|
||||
<event name="OnDataViewCtrlItemBeginDrag">OnBrowserBeginDrag</event>
|
||||
<event name="OnDataViewCtrlItemDrop">OnBrowserDrop</event>
|
||||
<event name="OnDataViewCtrlItemDropPossible">OnBrowserDropPossible</event>
|
||||
<event name="OnDataViewCtrlItemEditingDone">OnBrowserFilenameChanged</event>
|
||||
<event name="OnDataViewCtrlItemExpanding">OnBrowserDirectoryExpanding</event>
|
||||
<event name="OnDataViewCtrlSelectionChanged">OnBrowserSelectionChanged</event>
|
||||
@@ -2597,7 +2600,7 @@
|
||||
<property name="resize">Resizable</property>
|
||||
<property name="show">1</property>
|
||||
<property name="size"></property>
|
||||
<property name="style">wxGA_HORIZONTAL</property>
|
||||
<property name="style">wxGA_HORIZONTAL|wxGA_SMOOTH</property>
|
||||
<property name="subclass">; ; forward_declare</property>
|
||||
<property name="toolbar_pane">0</property>
|
||||
<property name="tooltip"></property>
|
||||
|
||||
@@ -132,6 +132,9 @@ class MainWindowGen : public wxFrame
|
||||
virtual void OnBrowserRenameMenuItem( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserDeleteMenuItem( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserFormatButton( wxCommandEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserBeginDrag( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserDrop( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserDropPossible( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserFilenameChanged( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserDirectoryExpanding( wxDataViewEvent& event ) { event.Skip(); }
|
||||
virtual void OnBrowserSelectionChanged( wxDataViewEvent& event ) { event.Skip(); }
|
||||
|
||||
@@ -42,13 +42,25 @@ const std::string DEFAULT_EXTRA_CONFIGURATION =
|
||||
"# or the name of a built-in configuration, or the filename\n"
|
||||
"# of a text proto file. Or a comment, of course.\n\n";
|
||||
|
||||
const std::string DND_TYPE = "fluxengine.files";
|
||||
|
||||
class CancelException
|
||||
{
|
||||
};
|
||||
|
||||
class MainWindow : public MainWindowGen
|
||||
{
|
||||
private:
|
||||
class FilesystemOperation;
|
||||
|
||||
public:
|
||||
MainWindow(): MainWindowGen(nullptr), _config("FluxEngine")
|
||||
MainWindow():
|
||||
MainWindowGen(nullptr),
|
||||
/* This is wrong. Apparently the wxDataViewCtrl doesn't work properly
|
||||
* with DnD unless the format is wxDF_UNICODETEXT. It should be a custom
|
||||
* value. */
|
||||
_dndFormat(wxDF_UNICODETEXT),
|
||||
_config("FluxEngine")
|
||||
{
|
||||
Logger::setLogger(
|
||||
[&](std::shared_ptr<const AnyLogMessage> message)
|
||||
@@ -116,6 +128,13 @@ public:
|
||||
NULL,
|
||||
this);
|
||||
|
||||
/* This is a bug workaround for an issue where the calculation of the
|
||||
* item being dropped on is wrong due to the header not being taken into
|
||||
* account. See https://forums.wxwidgets.org/viewtopic.php?t=44752. */
|
||||
|
||||
browserTree->EnableDragSource(_dndFormat);
|
||||
browserTree->EnableDropTarget(_dndFormat);
|
||||
|
||||
/* I have no idea why this is necessary, but on Windows things aren't
|
||||
* laid out correctly without it. */
|
||||
|
||||
@@ -612,28 +631,31 @@ public:
|
||||
return path;
|
||||
}
|
||||
|
||||
void OnBrowserAddMenuItem(wxCommandEvent&) override
|
||||
std::shared_ptr<FilesystemNode> GetTargetDirectoryNode(wxDataViewItem& item)
|
||||
{
|
||||
Path dirPath;
|
||||
auto item = browserTree->GetSelection();
|
||||
Path path;
|
||||
if (item.IsOk())
|
||||
{
|
||||
auto dirNode = _filesystemModel->Find(item);
|
||||
if (!dirNode)
|
||||
return;
|
||||
dirPath = dirNode->dirent->path;
|
||||
auto node = _filesystemModel->Find(item);
|
||||
if (!node)
|
||||
return nullptr;
|
||||
path = node->dirent->path;
|
||||
}
|
||||
|
||||
auto dirNode = _filesystemModel->Find(dirPath);
|
||||
auto node = _filesystemModel->Find(path);
|
||||
if (!node)
|
||||
return nullptr;
|
||||
if (node->dirent->file_type != TYPE_DIRECTORY)
|
||||
return _filesystemModel->Find(path.parent());
|
||||
return node;
|
||||
}
|
||||
|
||||
void OnBrowserAddMenuItem(wxCommandEvent&) override
|
||||
{
|
||||
auto item = browserTree->GetSelection();
|
||||
auto dirNode = GetTargetDirectoryNode(item);
|
||||
if (!dirNode)
|
||||
return;
|
||||
if (dirNode->dirent->file_type != TYPE_DIRECTORY)
|
||||
{
|
||||
dirPath = dirPath.parent();
|
||||
dirNode = _filesystemModel->Find(dirPath);
|
||||
if (!dirNode)
|
||||
return;
|
||||
}
|
||||
|
||||
auto localPath = wxFileSelector("Choose the name of the file to add",
|
||||
/* default_path= */ wxEmptyString,
|
||||
@@ -644,11 +666,11 @@ public:
|
||||
.ToStdString();
|
||||
if (localPath.empty())
|
||||
return;
|
||||
Path path = dirPath;
|
||||
path.push_back(wxFileName(localPath).GetFullName().ToStdString());
|
||||
auto path = dirNode->dirent->path.concat(
|
||||
wxFileName(localPath).GetFullName().ToStdString());
|
||||
|
||||
QueueBrowserOperation(
|
||||
[this, path, localPath, item]() mutable
|
||||
[this, path, localPath]() mutable
|
||||
{
|
||||
path = ResolveFileConflicts_WT(path);
|
||||
if (path.empty())
|
||||
@@ -672,6 +694,8 @@ public:
|
||||
{
|
||||
auto item = browserTree->GetSelection();
|
||||
auto node = _filesystemModel->Find(item);
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
QueueBrowserOperation(
|
||||
[this, node]()
|
||||
@@ -720,13 +744,14 @@ public:
|
||||
|
||||
if (node->newname.empty())
|
||||
return;
|
||||
if (node->newname == node->dirent->filename)
|
||||
return;
|
||||
|
||||
QueueBrowserOperation(
|
||||
[this, node]() mutable
|
||||
{
|
||||
auto oldPath = node->dirent->path;
|
||||
auto newPath = oldPath.parent();
|
||||
newPath.push_back(node->newname);
|
||||
auto newPath = oldPath.parent().concat(node->newname);
|
||||
|
||||
newPath = ResolveFileConflicts_WT(newPath);
|
||||
if (newPath.empty())
|
||||
@@ -756,8 +781,12 @@ public:
|
||||
if (d.ShowModal() != wxID_OK)
|
||||
return;
|
||||
|
||||
auto oldPath = node->dirent->path;
|
||||
auto newPath = Path(d.newNameText->GetValue().ToStdString());
|
||||
ActuallyMoveFile(
|
||||
node->dirent->path, Path(d.newNameText->GetValue().ToStdString()));
|
||||
}
|
||||
|
||||
void ActuallyMoveFile(const Path& oldPath, Path newPath)
|
||||
{
|
||||
QueueBrowserOperation(
|
||||
[this, oldPath, newPath]() mutable
|
||||
{
|
||||
@@ -780,26 +809,11 @@ public:
|
||||
|
||||
void OnBrowserNewDirectoryMenuItem(wxCommandEvent& event)
|
||||
{
|
||||
Path path;
|
||||
auto item = browserTree->GetSelection();
|
||||
if (item.IsOk())
|
||||
{
|
||||
auto node = _filesystemModel->Find(item);
|
||||
if (!node)
|
||||
return;
|
||||
path = node->dirent->path;
|
||||
}
|
||||
|
||||
auto node = _filesystemModel->Find(path);
|
||||
auto node = GetTargetDirectoryNode(item);
|
||||
if (!node)
|
||||
return;
|
||||
if (node->dirent->file_type != TYPE_DIRECTORY)
|
||||
{
|
||||
path = path.parent();
|
||||
node = _filesystemModel->Find(path);
|
||||
if (!node)
|
||||
return;
|
||||
}
|
||||
auto path = node->dirent->path;
|
||||
|
||||
CreateDirectoryDialog d(this, wxID_ANY);
|
||||
d.newNameText->SetValue(path.to_str() + "/");
|
||||
@@ -823,6 +837,79 @@ public:
|
||||
});
|
||||
}
|
||||
|
||||
void OnBrowserBeginDrag(wxDataViewEvent& event) override
|
||||
{
|
||||
auto item = browserTree->GetSelection();
|
||||
if (!item.IsOk())
|
||||
{
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
||||
auto node = _filesystemModel->Find(item);
|
||||
if (!node)
|
||||
{
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
||||
wxTextDataObject* obj = new wxTextDataObject();
|
||||
obj->SetText(node->dirent->path.to_str());
|
||||
event.SetDataObject(obj);
|
||||
event.SetDataFormat(_dndFormat);
|
||||
}
|
||||
|
||||
void OnBrowserDropPossible(wxDataViewEvent& event) override
|
||||
{
|
||||
if (event.GetDataFormat() != _dndFormat)
|
||||
{
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void OnBrowserDrop(wxDataViewEvent& event) override
|
||||
{
|
||||
try
|
||||
{
|
||||
if (event.GetDataFormat() != _dndFormat)
|
||||
throw CancelException();
|
||||
|
||||
/* wxWidgets 3.0 data view DnD is borked. See
|
||||
* https://forums.wxwidgets.org/viewtopic.php?t=44752. The hit
|
||||
* detection is done against the wrong object, resulting in the
|
||||
* header size not being taken into account, so we have to manually
|
||||
* do hit detection correctly. */
|
||||
|
||||
auto* window = browserTree->GetMainWindow();
|
||||
auto screenPos = wxGetMousePosition();
|
||||
auto relPos = screenPos - window->GetScreenPosition();
|
||||
|
||||
wxDataViewItem item;
|
||||
wxDataViewColumn* column;
|
||||
browserTree->HitTest(relPos, item, column);
|
||||
if (!item.IsOk())
|
||||
throw CancelException();
|
||||
|
||||
auto destDirNode = GetTargetDirectoryNode(item);
|
||||
if (!destDirNode)
|
||||
throw CancelException();
|
||||
auto destDirPath = destDirNode->dirent->path;
|
||||
|
||||
wxTextDataObject obj;
|
||||
obj.SetData(_dndFormat, event.GetDataSize(), event.GetDataBuffer());
|
||||
auto srcPath = Path(obj.GetText().ToStdString());
|
||||
if (srcPath.empty())
|
||||
throw CancelException();
|
||||
|
||||
ActuallyMoveFile(srcPath, destDirPath.concat(srcPath.back()));
|
||||
}
|
||||
catch (const CancelException& e)
|
||||
{
|
||||
event.Veto();
|
||||
}
|
||||
}
|
||||
|
||||
void OnBrowserCommitButton(wxCommandEvent&) override
|
||||
{
|
||||
QueueBrowserOperation(
|
||||
@@ -1378,6 +1465,7 @@ private:
|
||||
};
|
||||
|
||||
wxConfig _config;
|
||||
wxDataFormat _dndFormat;
|
||||
std::vector<std::pair<std::string, std::unique_ptr<const ConfigProto>>>
|
||||
_formats;
|
||||
std::vector<std::unique_ptr<const CandidateDevice>> _devices;
|
||||
|
||||
Reference in New Issue
Block a user