summaryrefslogtreecommitdiff
path: root/ui/main_dlg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/main_dlg.cpp')
-rw-r--r--ui/main_dlg.cpp188
1 files changed, 125 insertions, 63 deletions
diff --git a/ui/main_dlg.cpp b/ui/main_dlg.cpp
index 2d52d45e..0004d2fc 100644
--- a/ui/main_dlg.cpp
+++ b/ui/main_dlg.cpp
@@ -55,6 +55,7 @@
#include <wx+/no_flicker.h>
#include <wx+/grid.h>
#include "../lib/error_log.h"
+#include "triple_splitter.h"
using namespace zen;
using namespace std::rel_ops;
@@ -309,23 +310,23 @@ void setMenuItemImage(wxMenuItem*& menuItem, const wxBitmap& bmp)
if (wxMenu* menu = menuItem->GetMenu())
{
- int pos = menu->GetMenuItems().IndexOf(menuItem);
- if (pos != wxNOT_FOUND)
- {
- /*
- menu->Remove(item); ->this simple sequence crashes on Kubuntu x64, wxWidgets 2.9.2
- menu->Insert(index, item);
- */
- const bool enabled = menuItem->IsEnabled();
- wxMenuItem* newItem = new wxMenuItem(menu, menuItem->GetId(), menuItem->GetItemLabel());
- newItem->SetBitmap(bmp);
-
- menu->Destroy(menuItem); //actual workaround
- menuItem = menu->Insert(pos, newItem); //don't forget to update input item pointer!
-
- if (!enabled)
- menuItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason
- }
+ int pos = menu->GetMenuItems().IndexOf(menuItem);
+ if (pos != wxNOT_FOUND)
+ {
+ /*
+ menu->Remove(item); ->this simple sequence crashes on Kubuntu x64, wxWidgets 2.9.2
+ menu->Insert(index, item);
+ */
+ const bool enabled = menuItem->IsEnabled();
+ wxMenuItem* newItem = new wxMenuItem(menu, menuItem->GetId(), menuItem->GetItemLabel());
+ newItem->SetBitmap(bmp);
+
+ menu->Destroy(menuItem); //actual workaround
+ menuItem = menu->Insert(pos, newItem); //don't forget to update input item pointer!
+
+ if (!enabled)
+ menuItem->Enable(false); //do not enable BEFORE appending item! wxWidgets screws up for yet another crappy reason
+ }
}
}
@@ -578,7 +579,7 @@ MainDialog::MainDialog(const xmlAccess::XmlGuiConfig& guiCfg,
//init handling of first folder pair
firstFolderPair.reset(new DirectoryPairFirst(*this));
- initViewFilterButtons();
+ //initViewFilterButtons();
//init grid settings
gridview::init(*m_gridMainL, *m_gridMainC, *m_gridMainR, gridDataView);
@@ -783,6 +784,7 @@ void MainDialog::onQueryEndSession()
catch (const xmlAccess::FfsXmlError&) {}
}
+
void MainDialog::setGlobalCfgOnInit(const xmlAccess::XmlGlobalSettings& globalSettings)
{
globalCfg = globalSettings;
@@ -930,7 +932,7 @@ void MainDialog::setSyncDirManually(const std::vector<FileSystemObject*>& select
}
-void MainDialog::setManualFilter(const std::vector<FileSystemObject*>& selection, bool setIncluded)
+void MainDialog::setFilterManually(const std::vector<FileSystemObject*>& selection, bool setIncluded)
{
//if hidefiltered is active, there should be no filtered elements on screen => current element was filtered out
assert(currentCfg.showFilteredElements || !setIncluded);
@@ -940,7 +942,7 @@ void MainDialog::setManualFilter(const std::vector<FileSystemObject*>& selection
std::for_each(selection.begin(), selection.end(),
[&](FileSystemObject* fsObj) { zen::setActiveStatus(setIncluded, *fsObj); }); //works recursively for directories
- updateGuiAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true and to handle some graphical artifacts
+ updateGuiDelayedIf(!currentCfg.showFilteredElements); //show update GUI before removing rows
}
}
@@ -1170,7 +1172,7 @@ void MainDialog::deleteSelectedFiles(const std::vector<FileSystemObject*>& selec
if (!selectionLeft.empty() || !selectionRight.empty())
{
wxWindow* oldFocus = wxWindow::FindFocus();
- ZEN_ON_SCOPE_EXIT( if (oldFocus) oldFocus->SetFocus(); )
+ ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus();)
if (zen::showDeleteDialog(this,
selectionLeft,
@@ -1382,7 +1384,8 @@ void MainDialog::disableAllElements(bool enableAbort)
//show abort button
m_buttonAbort->Enable();
m_buttonAbort->Show();
- if (m_buttonAbort->IsShownOnScreen()) m_buttonAbort->SetFocus();
+ if (m_buttonAbort->IsShownOnScreen())
+ m_buttonAbort->SetFocus();
m_buttonCompare->Disable();
m_buttonCompare->Hide();
m_panelTopButtons->Layout();
@@ -1536,9 +1539,9 @@ void MainDialog::onTreeButtonEvent(wxKeyEvent& event)
case WXK_SPACE:
case WXK_NUMPAD_SPACE:
{
- const auto& selection = getTreeSelection();
+ const std::vector<FileSystemObject*>& selection = getTreeSelection();
if (!selection.empty())
- setManualFilter(selection, !selection[0]->isActive());
+ setFilterManually(selection, !selection[0]->isActive());
}
return;
@@ -1622,9 +1625,9 @@ void MainDialog::onGridButtonEvent(wxKeyEvent& event, Grid& grid, bool leftSide)
case WXK_SPACE:
case WXK_NUMPAD_SPACE:
{
- const auto& selection = getGridSelection();
+ const std::vector<FileSystemObject*>& selection = getGridSelection();
if (!selection.empty())
- setManualFilter(selection, !selection[0]->isActive());
+ setFilterManually(selection, !selection[0]->isActive());
}
return;
@@ -1718,14 +1721,16 @@ void MainDialog::OnGlobalKeyEvent(wxKeyEvent& event) //process key events withou
if (!isPartOf(focus, m_gridMainL ) && //
!isPartOf(focus, m_gridMainC ) && //don't propagate keyboard commands if grid is already in focus
!isPartOf(focus, m_gridMainR ) && //
+ !isPartOf(focus, m_gridNavi ) &&
!isPartOf(focus, m_listBoxHistory) && //don't propagate if selecting config
!isPartOf(focus, m_directoryLeft) && //don't propagate if changing directory field
!isPartOf(focus, m_directoryRight) &&
- !isPartOf(focus, m_gridNavi ) &&
!isPartOf(focus, m_scrolledWindowFolderPairs))
- if (wxEvtHandler* evtHandler = m_gridMainL->GetEventHandler())
+ if (wxEvtHandler* evtHandler = m_gridMainL->getMainWin().GetEventHandler())
{
m_gridMainL->SetFocus();
+
+ event.SetEventType(wxEVT_KEY_DOWN); //the grid event handler doesn't expect wxEVT_CHAR_HOOK!
evtHandler->ProcessEvent(event); //propagating event catched at wxTheApp to child leads to recursion, but we prevented it...
event.Skip(false); //definitively handled now!
return;
@@ -1827,9 +1832,9 @@ void MainDialog::onNaviGridContext(GridClickEvent& event)
if (!selection.empty())
{
if (selection[0]->isActive())
- menu.addItem(_("Exclude temporarily") + L"\tSpace", [this, &selection] { setManualFilter(selection, false); }, &GlobalResources::getImage(L"checkboxFalse"));
+ menu.addItem(_("Exclude temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, false); }, &GlobalResources::getImage(L"checkboxFalse"));
else
- menu.addItem(_("Include temporarily") + L"\tSpace", [this, &selection] { setManualFilter(selection, true); }, &GlobalResources::getImage(L"checkboxTrue"));
+ menu.addItem(_("Include temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, true); }, &GlobalResources::getImage(L"checkboxTrue"));
}
else
menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false);
@@ -1871,7 +1876,7 @@ void MainDialog::onMainGridContextC(GridClickEvent& event)
menu.addItem(_("Exclude all"), [&]
{
zen::setActiveStatus(false, folderCmp);
- updateGuiAfterFilterChange(400); //call this instead of updateGuiGrid() to add some delay if hideFiltered == true
+ updateGuiDelayedIf(!currentCfg.showFilteredElements); //show update GUI before removing rows
}, nullptr, gridDataView->rowsTotal() > 0);
menu.popup(*this);
@@ -1919,9 +1924,9 @@ void MainDialog::onMainGridContextRim(bool leftSide)
if (!selection.empty())
{
if (selection[0]->isActive())
- menu.addItem(_("Exclude temporarily") + L"\tSpace", [this, &selection] { setManualFilter(selection, false); }, &GlobalResources::getImage(L"checkboxFalse"));
+ menu.addItem(_("Exclude temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, false); }, &GlobalResources::getImage(L"checkboxFalse"));
else
- menu.addItem(_("Include temporarily") + L"\tSpace", [this, &selection] { setManualFilter(selection, true); }, &GlobalResources::getImage(L"checkboxTrue"));
+ menu.addItem(_("Include temporarily") + L"\tSpace", [this, &selection] { setFilterManually(selection, true); }, &GlobalResources::getImage(L"checkboxTrue"));
}
else
menu.addItem(_("Exclude temporarily") + L"\tSpace", [] {}, nullptr, false);
@@ -2163,7 +2168,8 @@ void MainDialog::onGridLabelContext(Grid& grid, ColumnTypeRim type, const std::v
if (showSelectTimespanDlg(this, manualTimeSpanFrom, manualTimeSpanTo) == ReturnSmallDlg::BUTTON_OKAY)
{
applyTimeSpanFilter(folderCmp, manualTimeSpanFrom, manualTimeSpanTo); //overwrite current active/inactive settings
- updateGuiAfterFilterChange(400);
+ //updateGuiDelayedIf(!currentCfg.showFilteredElements); //show update GUI before removing rows
+ updateGui();
}
};
menu.addItem(_("Select time span..."), selectTimeSpan);
@@ -2376,7 +2382,7 @@ void MainDialog::updateUnsavedCfgStatus()
setImage(*m_bpButtonSave, allowSave ? GlobalResources::getImage(L"save") : makeBrightGrey(GlobalResources::getImage(L"save")));
m_bpButtonSave->Enable(allowSave);
- m_menuItemSave->Enable(allowSave); //bitmap is automatically greyscaled on Win7 (introducing a crappy looking shift), but not on XP
+ m_menuItemSave->Enable(allowSave); //bitmap is automatically greyscaled on Win7 (introducing a crappy looking shift), but not on XP
//set main dialog title
wxString title;
@@ -2551,31 +2557,50 @@ void MainDialog::OnLoadFromHistory(wxCommandEvent& event)
});
if (!filenames.empty())
- {
loadConfiguration(filenames);
- //in case user cancelled saving old config, selection is wrong: so reapply it!
- addFileToCfgHistory(activeConfigFiles);
- }
+ //user changed m_listBoxHistory selection so it's this method's responsibility to synchronize with activeConfigFiles
+ //- if user cancelled saving old config
+ //- there's an error loading new config
+ //- filenames is empty and user tried to unselect the current config
+ addFileToCfgHistory(activeConfigFiles);
}
-void MainDialog::loadConfiguration(const wxString& filename)
+void MainDialog::OnLoadFromHistoryDoubleClick(wxCommandEvent& event)
{
+ wxArrayInt selections;
+ m_listBoxHistory->GetSelections(selections);
+
std::vector<wxString> filenames;
- filenames.push_back(filename);
+ std::for_each(selections.begin(), selections.end(),
+ [&](int pos)
+ {
+ if (auto histData = dynamic_cast<const wxClientHistoryData*>(m_listBoxHistory->GetClientObject(pos)))
+ filenames.push_back(histData->cfgFile_);
+ });
- loadConfiguration(filenames);
+ if (!filenames.empty())
+ if (loadConfiguration(filenames))
+ {
+ //simulate button click on "compare"
+ wxCommandEvent dummy2(wxEVT_COMMAND_BUTTON_CLICKED);
+ if (wxEvtHandler* evtHandler = m_buttonCompare->GetEventHandler())
+ evtHandler->ProcessEvent(dummy2); //synchronous call
+ }
+
+ //synchronize m_listBoxHistory and activeConfigFiles, see OnLoadFromHistory()
+ addFileToCfgHistory(activeConfigFiles);
}
-void MainDialog::loadConfiguration(const std::vector<wxString>& filenames)
+bool MainDialog::loadConfiguration(const std::vector<wxString>& filenames)
{
if (filenames.empty())
- return;
+ return true;
if (!saveOldConfig())
- return;
+ return false; //cancelled by user
//load XML
xmlAccess::XmlGuiConfig newGuiCfg; //structure to receive gui settings, already defaulted!!
@@ -2586,6 +2611,7 @@ void MainDialog::loadConfiguration(const std::vector<wxString>& filenames)
setConfig(newGuiCfg, filenames);
//flashStatusInformation(_("Configuration loaded!")); -> irrelvant!?
+ return true;
}
catch (const xmlAccess::FfsXmlError& error)
{
@@ -2597,6 +2623,7 @@ void MainDialog::loadConfiguration(const std::vector<wxString>& filenames)
}
else
wxMessageBox(error.toString(), _("Error"), wxOK | wxICON_ERROR, this);
+ return false;
}
}
@@ -2670,7 +2697,7 @@ void MainDialog::onCheckRows(CheckRowsEvent& event)
selectedRows.insert(i);
std::vector<FileSystemObject*> objects = gridDataView->getAllFileRef(selectedRows);
- setManualFilter(objects, event.setIncluded_);
+ setFilterManually(objects, event.setIncluded_);
}
}
@@ -2720,7 +2747,7 @@ void MainDialog::setConfig(const xmlAccess::XmlGuiConfig& newGuiCfg, const std::
//evaluate new settings...
//(re-)set view filter buttons
- initViewFilterButtons();
+ initViewFilterButtons(newGuiCfg.mainCfg);
updateFilterButtons();
@@ -2803,18 +2830,18 @@ const wxString& MainDialog::lastRunConfigName()
}
-void MainDialog::updateGuiAfterFilterChange(int delay)
+void MainDialog::updateGuiDelayedIf(bool condition)
{
- //signal UI that grids need to be refreshed on next Update()
+ const int delay = 400;
- if (!currentCfg.showFilteredElements)
+ if (condition)
{
gridview::refresh(*m_gridMainL, *m_gridMainC, *m_gridMainR);
m_gridMainL->Update();
m_gridMainC->Update();
m_gridMainR->Update();
- wxMilliSleep(delay); //some delay to show user the rows he has filtered out before they are removed
+ wxMilliSleep(delay); //some delay to show the changed GUI before removing rows from sight
}
updateGui();
@@ -2982,7 +3009,7 @@ wxBitmap buttonReleased(const std::string& name)
}
-void MainDialog::initViewFilterButtons()
+void MainDialog::initViewFilterButtons(const MainConfiguration& mainCfg)
{
//compare result buttons
m_bpButtonLeftOnly->init(buttonPressed("leftOnly"),
@@ -3061,7 +3088,6 @@ void MainDialog::initViewFilterButtons()
m_bpButtonRightOnly-> setActive(true);
m_bpButtonLeftNewer-> setActive(true);
m_bpButtonRightNewer->setActive(true);
- m_bpButtonEqual-> setActive(false);
m_bpButtonDifferent-> setActive(true);
m_bpButtonConflict-> setActive(true);
@@ -3072,7 +3098,46 @@ void MainDialog::initViewFilterButtons()
m_bpButtonSyncDeleteRight-> setActive(true);
m_bpButtonSyncDirOverwLeft-> setActive(true);
m_bpButtonSyncDirOverwRight->setActive(true);
- m_bpButtonSyncDirNone-> setActive(true);
+
+ m_bpButtonEqual->setActive(false);
+
+ //special case "m_bpButtonSyncDirNone": set always active, unless sync direction "none" is part of the rule set:
+ //e.g. for a "custom" config or "update" variant. Otherwise rows with sync direction "none" can only occur on grid if the user manually
+ //sets them, in which case these rows should not be hidden immediately, so m_bpButtonSyncDirNone must be active
+ const std::vector<FolderPairCfg>& cmpCfg = extractCompareCfg(mainCfg);
+ const bool syncDirNonePartOfConfig = std::any_of(cmpCfg.begin(), cmpCfg.end(),
+ [&](const FolderPairCfg& fpCfg) -> bool
+ {
+ //attention: following is quite an amount of implicit/redundant knowledge here... let's hope our model is fundamental enough to not change any time soon!
+
+ if (fpCfg.directionCfg.var == DirectionConfig::AUTOMATIC)
+ return false;
+
+ const DirectionSet dirSet = extractDirections(fpCfg.directionCfg);
+
+ switch (fpCfg.compareVar)
+ {
+ case CMP_BY_TIME_SIZE:
+ return dirSet.exLeftSideOnly == SYNC_DIR_NONE ||
+ dirSet.exRightSideOnly == SYNC_DIR_NONE ||
+ dirSet.leftNewer == SYNC_DIR_NONE ||
+ dirSet.rightNewer == SYNC_DIR_NONE;
+ //dirSet.different == SYNC_DIR_NONE ||
+ //dirSet.conflict == SYNC_DIR_NONE;
+
+ case CMP_BY_CONTENT:
+ return dirSet.exLeftSideOnly == SYNC_DIR_NONE ||
+ dirSet.exRightSideOnly == SYNC_DIR_NONE ||
+ //dirSet.leftNewer == SYNC_DIR_NONE ||
+ //dirSet.rightNewer == SYNC_DIR_NONE ||
+ dirSet.different == SYNC_DIR_NONE;
+ //dirSet.conflict == SYNC_DIR_NONE;
+ }
+ assert(false);
+ return false;
+ });
+
+ m_bpButtonSyncDirNone->setActive(!syncDirNonePartOfConfig);
}
@@ -3105,7 +3170,7 @@ void MainDialog::OnCompare(wxCommandEvent& event)
wxBusyCursor dummy; //show hourglass cursor
wxWindow* oldFocus = wxWindow::FindFocus();
- ZEN_ON_SCOPE_EXIT( if (oldFocus) oldFocus->SetFocus(); ); //e.g. keep focus on main grid after pressing F5
+ ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus();) //e.g. keep focus on main grid after pressing F5
int scrollPosX = 0;
int scrollPosY = 0;
@@ -3169,7 +3234,7 @@ void MainDialog::OnCompare(wxCommandEvent& event)
//add to folder history after successful comparison only
folderHistoryLeft ->addItem(toZ(m_directoryLeft->GetValue()));
folderHistoryRight->addItem(toZ(m_directoryRight->GetValue()));
-
+
//prepare status information
if (allElementsEqual(folderCmp))
flashStatusInformation(_("All folders are in sync!"));
@@ -3378,11 +3443,6 @@ void MainDialog::OnStartSync(wxCommandEvent& event)
syncProcessCfg,
folderCmp,
statusHandler);
-
- //play (optional) sound notification after sync has completed (GUI and batch mode)
- const wxString soundFile = toWx(zen::getResourceDir()) + L"Sync_Complete.wav";
- if (fileExists(toZ(soundFile)))
- wxSound::Play(soundFile, wxSOUND_ASYNC);
}
catch (GuiAbortProcess&)
{
@@ -3674,7 +3734,9 @@ void MainDialog::updateGridViewData()
void MainDialog::applyFilterConfig()
{
applyFiltering(folderCmp, getConfig().mainCfg);
- updateGuiAfterFilterChange(400);
+
+ updateGui();
+ //updateGuiDelayedIf(!currentCfg.showFilteredElements); //show update GUI before removing rows
}
@@ -3771,7 +3833,7 @@ void MainDialog::updateGuiForFolderPair()
m_bpButtonLocalFilter->Show(showLocalCfgFirstPair);
setImage(*m_bpButtonSwapSides, GlobalResources::getImage(showLocalCfgFirstPair ? L"swapSlim" : L"swap"));
m_panelTopMiddle->Layout(); //both required to update button size for calculations below!!!
- m_panelDirectoryPairs->Layout(); // -> updates size of stretched m_panelTopLeft!
+ m_panelDirectoryPairs->Layout(); // -> updates size of stretched m_panelTopLeft!
int addPairMinimalHeight = 0;
int addPairOptimalHeight = 0;
bgstack15