summaryrefslogtreecommitdiff
path: root/ui/exec_finished_box.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/exec_finished_box.cpp')
-rw-r--r--ui/exec_finished_box.cpp270
1 files changed, 270 insertions, 0 deletions
diff --git a/ui/exec_finished_box.cpp b/ui/exec_finished_box.cpp
new file mode 100644
index 00000000..49c490ad
--- /dev/null
+++ b/ui/exec_finished_box.cpp
@@ -0,0 +1,270 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) 2008-2011 ZenJu (zhnmju123 AT gmx.de) *
+// **************************************************************************
+
+#include "exec_finished_box.h"
+#include <deque>
+#include <zen/i18n.h>
+#include <algorithm>
+#include <zen/stl_tools.h>
+#ifdef FFS_WIN
+#include <zen/win_ver.h>
+#endif
+
+using namespace zen;
+
+
+namespace
+{
+const std::wstring closeProgressDlg = L"Close progress dialog"; //special command //mark for extraction: _("Close progress dialog")
+
+const std::wstring separationLine(L"---------------------------------------------------------------------------------------------------------------");
+
+std::vector<std::pair<std::wstring, std::wstring>> getDefaultCommands() //(gui name/command) pairs
+{
+ std::vector<std::pair<std::wstring, std::wstring>> output;
+
+ auto addEntry = [&](const std::wstring& name, const std::wstring& value) { output.push_back(std::make_pair(name, value)); };
+
+#ifdef FFS_WIN
+ if (zen::vistaOrLater())
+ {
+ addEntry(_("Shut down"), L"shutdown /s /t 60");
+ addEntry(_("Log off" ), L"shutdown /l");
+ addEntry(_("Standby" ), L"rundll32.exe powrprof.dll,SetSuspendState Sleep"); //suspend/Suspend to RAM/sleep
+ //addEntry(_("Hibernate"), L"shutdown /h"); //Suspend to disk -> Standby is better anyway
+ }
+ else //XP
+ {
+ addEntry(_("Shut down"), L"shutdown -s -t 60");
+ addEntry(_("Log off" ), L"shutdown -l");
+ //no suspend on XP?
+ addEntry(_("Standby"), L"rundll32.exe powrprof.dll,SetSuspendState"); //this triggers standby OR hibernate, depending on whether hibernate setting is active!
+ }
+
+#elif defined FFS_LINUX
+ addEntry(_("Shut down"), L"dbus-send --print-reply --dest=org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.RequestShutdown");
+ //alternative requiring admin: sudo shutdown -h 1
+ addEntry(_("Log off" ), L"gnome-session-quit"); //alternative requiring admin: sudo killall Xorg
+ addEntry(_("Standby" ), L"sudo pm-suspend");
+ //addEntry(_("Hibernate"), L"sudo pm-hibernate");
+ //alternative: "pmi action suspend" and "pmi action hibernate", require "sudo apt-get install powermanagement-interaface"
+
+#endif
+ return output;
+}
+
+const wxEventType wxEVT_REPLACE_BUILT_IN_COMMANDS = wxNewEventType();
+}
+
+
+bool isCloseProgressDlgCommand(const std::wstring& value)
+{
+ std::wstring tmp = value;
+ trim(tmp);
+ return tmp == closeProgressDlg;
+}
+
+
+void addValueToHistory(const std::wstring& value, std::vector<std::wstring>& history, size_t historyMax)
+{
+ std::wstring command = value;
+ trim(command);
+
+ bool skipCmd = command == separationLine || //do not add sep. line
+ command == closeProgressDlg || //do not add special command
+ command.empty();
+
+ //do not add built-in commands to history
+ if (!skipCmd)
+ {
+ const auto& defaultCommands = getDefaultCommands();
+ for (auto iter = defaultCommands.begin(); iter != defaultCommands.end(); ++iter)
+ if (command == iter->first || command == iter->second)
+ {
+ skipCmd = true;
+ break;
+ }
+ }
+
+ if (!skipCmd)
+ history.insert(history.begin(), command);
+
+ if (history.size() > historyMax)
+ history.resize(historyMax);
+}
+
+
+ExecFinishedBox::ExecFinishedBox(wxWindow* parent,
+ wxWindowID id,
+ const wxString& value,
+ const wxPoint& pos,
+ const wxSize& size,
+ int n,
+ const wxString choices[],
+ long style,
+ const wxValidator& validator,
+ const wxString& name) :
+ wxComboBox(parent, id, value, pos, size, n, choices, style, validator, name),
+ history_(NULL),
+ defaultCommands(getDefaultCommands())
+{
+ //#####################################
+ /*##*/ SetMinSize(wxSize(150, -1)); //## workaround yet another wxWidgets bug: default minimum size is much too large for a wxComboBox
+ //#####################################
+
+ Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (ExecFinishedBox::OnKeyEvent ), NULL, this);
+ Connect(wxEVT_LEFT_DOWN, wxEventHandler (ExecFinishedBox::OnUpdateList), NULL, this);
+ Connect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(ExecFinishedBox::OnSelection ), NULL, this);
+ Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (ExecFinishedBox::OnMouseWheel), NULL, this);
+
+ Connect(wxEVT_REPLACE_BUILT_IN_COMMANDS, wxCommandEventHandler(ExecFinishedBox::OnReplaceBuiltInCmds), NULL, this);
+}
+
+
+std::wstring ExecFinishedBox::getValue() const
+{
+ const std::wstring value = zen::copyStringTo<std::wstring>(GetValue());
+
+ {
+ std::wstring tmp = value;
+ trim(tmp);
+ if (tmp == implementation::translate(closeProgressDlg)) //have this symbolic constant translated properly
+ return closeProgressDlg;
+ }
+
+ return value;
+}
+
+
+void ExecFinishedBox::setValue(const std::wstring& value)
+{
+ std::wstring tmp = value;
+ trim(tmp);
+
+ if (tmp == closeProgressDlg)
+ setValueAndUpdateList(implementation::translate(closeProgressDlg)); //have this symbolic constant translated properly
+ else
+ setValueAndUpdateList(value);
+}
+
+//set value and update list are technically entangled: see potential bug description below
+void ExecFinishedBox::setValueAndUpdateList(const std::wstring& value)
+{
+ //it may be a little lame to update the list on each mouse-button click, but it should be working and we dont't have to manipulate wxComboBox internals
+
+ std::deque<std::wstring> items;
+
+ //1. special command
+ items.push_back(implementation::translate(closeProgressDlg));
+
+ //2. built in commands
+ for (auto iter = defaultCommands.begin(); iter != defaultCommands.end(); ++iter)
+ items.push_back(iter->first);
+
+ //3. history elements
+ if (history_ && !history_->empty())
+ {
+ items.push_back(separationLine);
+ items.insert(items.end(), history_->begin(), history_->end());
+ std::sort(items.end() - history_->size(), items.end());
+ }
+
+ //attention: if the target value is not part of the dropdown list, SetValue() will look for a string that *starts with* this value:
+ //e.g. if the dropdown list contains "222" SetValue("22") will erroneously set and select "222" instead, while "111" would be set correctly!
+ // -> by design on Windows!
+ if (std::find(items.begin(), items.end(), value) == items.end())
+ {
+ if (!value.empty())
+ items.push_front(separationLine);
+ items.push_front(value);
+ }
+
+ Clear();
+ std::for_each(items.begin(), items.end(), [&](const std::wstring& item) { this->Append(item); });
+ //this->SetSelection(wxNOT_FOUND); //don't select anything
+ SetValue(value); //preserve main text!
+}
+
+
+void ExecFinishedBox::OnSelection(wxCommandEvent& event)
+{
+ wxCommandEvent dummy2(wxEVT_REPLACE_BUILT_IN_COMMANDS); //we cannot replace built-in commands at this position in call stack, so defer to a later time!
+ GetEventHandler()->AddPendingEvent(dummy2); //
+
+ event.Skip();
+}
+
+
+void ExecFinishedBox::OnReplaceBuiltInCmds(wxCommandEvent& event)
+{
+ const auto& value = getValue();
+
+ if (value == separationLine)
+ setValueAndUpdateList(std::wstring());
+ else
+ for (auto iter = defaultCommands.begin(); iter != defaultCommands.end(); ++iter)
+ if (iter->first == value)
+ return setValueAndUpdateList(iter->second); //replace GUI name by actual command string
+}
+
+
+void ExecFinishedBox::OnUpdateList(wxEvent& event)
+{
+ setValue(getValue());
+ event.Skip();
+}
+
+
+void ExecFinishedBox::OnKeyEvent(wxKeyEvent& event)
+{
+ switch (event.GetKeyCode())
+ {
+ case WXK_DELETE:
+ case WXK_NUMPAD_DELETE:
+ {
+ //try to delete the currently selected config history item
+ int pos = this->GetCurrentSelection();
+ if (0 <= pos && pos < static_cast<int>(this->GetCount()) &&
+ //what a mess...:
+ (GetValue() != GetString(pos) || //avoid problems when a character shall be deleted instead of list item
+ GetValue() == wxEmptyString)) //exception: always allow removing empty entry
+ {
+ const std::wstring selValue = copyStringTo<std::wstring>(GetString(pos));
+
+ if (history_ && std::find(history_->begin(), history_->end(), selValue) != history_->end()) //only history elements may be deleted
+ {
+ //save old (selected) value: deletion seems to have influence on this
+ const wxString currentVal = this->GetValue();
+ //this->SetSelection(wxNOT_FOUND);
+
+ //delete selected row
+ vector_remove_if(*history_, [&](const std::wstring& item) { return item == selValue; });
+
+ SetString(pos, wxString()); //in contrast to Delete(), this one does not kill the drop-down list and gives a nice visual feedback!
+ //Delete(pos);
+
+ //(re-)set value
+ SetValue(currentVal);
+ }
+
+ //eat up key event
+ return;
+ }
+ }
+ break;
+
+ case WXK_UP:
+ case WXK_NUMPAD_UP:
+ case WXK_DOWN:
+ case WXK_NUMPAD_DOWN:
+ case WXK_PAGEUP:
+ case WXK_NUMPAD_PAGEUP:
+ case WXK_PAGEDOWN:
+ case WXK_NUMPAD_PAGEDOWN:
+ return; //swallow -> using these keys gives a weird effect due to this weird control
+ }
+ event.Skip();
+}
bgstack15