View Issue Details

IDProjectCategoryView StatusLast Update
0003080Far ManagerFindFilespublic2015-10-03 15:08
Reporter4eyes Assigned ToDrKnS  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version3.0 
Fixed in Version3.0 
Summary0003080: [patch] Alternate editor/viewer in FindFile results
DescriptionFindFile results list doesn't support custom editor/viewer for found files.

Although FAR may use file associations or editor/viewer configuration for customizing files opening method, these settings aren't applied for FindFile results.

Patch is included to this issue.
Forum link: http://forum.farmanager.com/viewtopic.php?f=6&t=9797
Steps To Reproduce - create Edit file association, or set up external editor using Editor options;
 - start search in FindFile;
 - wait for a first results;
 - try to open external editor, or editor associated with 'file associations'
Additional InformationI think, it would be nice and consistent if file associations and Editor/Viewer options were working globally for any files list. This patch is a little step further.

Additionally, with this patch user may launch external editor/viewer while search still in progress, which is impossible from temporary panel. Moreover, sometimes ind results dialog is more handy then temporary panel, due to short file name, grouping, etc.

Feel free to contact me here or on forum, if there is any suggestions to my patch.

TagsNo tags attached.
Build4430

Activities

4eyes

2015-09-02 09:09

reporter  

unicode_far_r13359_FindFileList.patch (16,288 bytes)   
Index: FarRus.hlf.m4
===================================================================
--- FarRus.hlf.m4	(revision 13359)
+++ FarRus.hlf.m4	(working copy)
@@ -1866,8 +1866,24 @@
 
    #Отмена#          Прервать поиск и закрыть диалог.
 
-    Для просмотра и редактирования найденных файлов могут быть использованы
-#F3# и #F4#. Редактирование и просмотр поддерживаются также для файловых систем
+    Во время поиска поддерживается просмотр и редактирование найденных файлов.
+
+  Просмотр                               #Ctrl-Shift-F3, Numpad 5, F3, ALT-F3#
+
+    #NumPad 5#, #F3# или #ALT-F3# используются для вызова ~встроенной~@Viewer@, внешней 
+    или ~ассоциированной~@FileAssoc@ программы просмотра, в зависимости от типа файла и 
+    ~настроек программы просмотра~@ViewerSettings@.
+    #Ctrl-Shift-F3# всегда вызывает встроенную программу просмотра, вне
+    зависимости от файловых ассоциаций.
+    
+  Редактирование                                   #Ctrl-Shift-F4, F4, ALT-F4#
+
+    #F4# или #ALT-F4# вызывает ~встроенный~@Editor@, внешний или ~ассоциированный~@FileAssoc@
+    редактор, в зависимости от типа файла и ~настроек редактора~@EditorSettings@.
+    #Ctrl-Shift-F4# всегда вызывает встроенный редактор, вне зависимости от
+    файловых ассоциаций.
+
+Редактирование и просмотр поддерживаются также для файловых систем
 плагинов. Заметьте, что сохранение изменений в редакторе по клавише
 #F2# для файловых систем плагинов будет вызывать операцию
 #Сохранить в# вместо обычного #Сохранить#.
Index: filetype.cpp
===================================================================
--- filetype.cpp	(revision 13359)
+++ filetype.cpp	(working copy)
@@ -245,6 +245,73 @@
 }
 
 
+bool GetFiletypeOpenMode(int keyPressed, FILETYPE_MODE& mode, bool& shouldForceInternal)
+{
+	bool isModeFound = false; 
+
+	switch (keyPressed)
+	{
+	case KEY_F3:
+	case KEY_NUMPAD5:
+	case KEY_SHIFTNUMPAD5:
+		mode = Global->Opt->ViOpt.UseExternalViewer ? FILETYPE_ALTVIEW : FILETYPE_VIEW;
+		shouldForceInternal = false;
+		isModeFound = true;
+		break;
+
+	case KEY_CTRLSHIFTF3:
+	case KEY_RCTRLSHIFTF3:
+		mode = FILETYPE_VIEW;
+		shouldForceInternal = true;
+		isModeFound = true;
+		break;
+
+	case KEY_RALTF3:
+	case KEY_ALTF3:
+		mode = !Global->Opt->ViOpt.UseExternalViewer ? FILETYPE_ALTVIEW : FILETYPE_VIEW;;
+		shouldForceInternal = false;
+		isModeFound = true;
+		break;
+
+	case KEY_F4:
+		mode = Global->Opt->EdOpt.UseExternalEditor ? FILETYPE_ALTEDIT: FILETYPE_EDIT;
+		shouldForceInternal = false;
+		isModeFound = true;
+		break;
+
+	case KEY_CTRLSHIFTF4:
+	case KEY_RCTRLSHIFTF4:
+		mode = FILETYPE_EDIT;
+		shouldForceInternal = true;
+		isModeFound = true;
+		break;
+
+	case KEY_ALTF4:
+	case KEY_RALTF4:
+		mode = !Global->Opt->EdOpt.UseExternalEditor ? FILETYPE_ALTEDIT : FILETYPE_EDIT;
+		shouldForceInternal = false;
+		isModeFound = true;
+		break;
+
+	case KEY_ENTER:
+		mode = FILETYPE_EXEC;
+		isModeFound = true;
+		break;
+
+	case KEY_CTRLPGDN:
+	case KEY_RCTRLPGDN:
+		mode = FILETYPE_ALTEXEC;
+		isModeFound = true;
+		break;
+
+	default:
+		// non-default key may be pressed, it's ok. 
+		break;
+	}
+
+	return isModeFound;
+}
+
 void ProcessGlobalFileTypes(const string& Name, bool AlwaysWaitFinish, bool RunAs, bool FromPanel)
 {
 	string strName(Name);
Index: filetype.hpp
===================================================================
--- filetype.hpp	(revision 13359)
+++ filetype.hpp	(working copy)
@@ -44,6 +44,13 @@
 	FILETYPE_ALTEDIT     // Alt-F4
 };
 
+/*
+ * Convert pressed key into FILETYPE_MODE operation, if possible.
+ * Won't change 'mode' if key is unknown
+ * return true if succeed.
+ */
+bool GetFiletypeOpenMode(int keyPressed, FILETYPE_MODE& mode, bool& shouldForceInternal);
+
 void ProcessGlobalFileTypes(const string& Name, bool AlwaysWaitFinish, bool RunAs,bool FromPanel=false);
 bool ProcessLocalFileTypes(const string& Name, const string& ShortName, FILETYPE_MODE Mode, bool AlwaysWaitFinish);
 void ProcessExternal(const string& Command, const string& Name, const string& ShortName, bool AlwaysWaitFinish);
Index: findfile.cpp
===================================================================
--- findfile.cpp	(revision 13359)
+++ findfile.cpp	(working copy)
@@ -78,6 +78,7 @@
 #include "filestr.hpp"
 #include "exitcode.hpp"
 #include "panelctype.hpp"
+#include "filetype.hpp"
 
 // ������ ������. ���� ���� ������ � �����, �� FindList->ArcIndex �������� ���.
 struct ArcListItem
@@ -101,7 +102,7 @@
 class InterThreadData
 {
 private:
-	CriticalSection DataCS;
+	mutable CriticalSection DataCS;
 	ArcListItem* FindFileArcItem;
 	int Percent;
 	int LastFoundNumber;
@@ -112,6 +113,8 @@
 	std::list<ArcListItem> ArcList;
 	string strFindMessage;
 
+	std::list<FindListItem>& GetFindList() { return FindList; }
+
 public:
 	InterThreadData() {Init();}
 	~InterThreadData() { ClearAllLists(); }
@@ -129,11 +132,7 @@
 		strFindMessage.clear();
 	}
 
-	std::list<FindListItem>& GetFindList() {return FindList;}
 
-	void Lock() {DataCS.lock();}
-	void Unlock() {DataCS.unlock();}
-
 	ArcListItem* GetFindFileArcItem()
 	{
 		SCOPED_ACTION(CriticalSectionLock)(DataCS);
@@ -178,7 +177,11 @@
 		DirCount = Value;
 	}
 
-	size_t GetFindListCount() const { return FindList.size(); }
+	size_t GetFindListCount() const 
+	{
+		SCOPED_ACTION(CriticalSectionLock)(DataCS); 
+		return FindList.size(); 
+	}
 
 	void GetFindMessage(string& To)
 	{
@@ -243,6 +246,23 @@
 		FindList.emplace_back(NewItem);
 		return FindList.back();
 	}
+
+	template <typename Visitor>
+	void ForEachFindItem(const Visitor& visitor) const
+	{
+		SCOPED_ACTION(CriticalSectionLock)(DataCS);
+		for (const auto& i : GetFindList())
+			visitor(i);
+	}
+
+	template <typename Visitor>
+	void ForEachFindItem(const Visitor& visitor) 
+	{
+		SCOPED_ACTION(CriticalSectionLock)(DataCS);
+		for (auto& i : GetFindList())
+			visitor(i);
+	}
+
 };
 
 
@@ -1578,9 +1598,17 @@
 			*/
 
 			case KEY_F3:
+			case KEY_ALTF3:
+			case KEY_RALTF3:
+			case KEY_CTRLSHIFTF3:
+			case KEY_RCTRLSHIFTF3:
 			case KEY_NUMPAD5:
 			case KEY_SHIFTNUMPAD5:
 			case KEY_F4:
+			case KEY_ALTF4:
+			case KEY_RALTF4:
+			case KEY_CTRLSHIFTF4:
+			case KEY_RCTRLSHIFTF4:
 				{
 					if (ListBox->empty())
 					{
@@ -1662,81 +1690,8 @@
 							strSearchFileName = FindItem->FindData.strAlternateFileName;
 					}
 
-					if (os::fs::exists(strSearchFileName))
-					{
-						const auto strOldTitle = Console().GetTitle();
+					OpenFile(strSearchFileName, key, FindItem, Dlg);
 
-						if (key==KEY_F3 || key==KEY_NUMPAD5 || key==KEY_SHIFTNUMPAD5)
-						{
-							NamesList ViewList;
-							int list_count = 0;
-
-							// ������ ��� ����, ������ ���� ������ �����...
-							itd->Lock();
-							std::for_each(CONST_RANGE(itd->GetFindList(), i)
-							{
-								bool RealNames=true;
-								if(i.Arc)
-								{
-									if(!(i.Arc->Flags & OPIF_REALNAMES))
-									{
-										RealNames=false;
-									}
-								}
-								if (RealNames)
-								{
-									if (!i.FindData.strFileName.empty() && !(i.FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
-									{
-										++list_count;
-										ViewList.AddName(i.FindData.strFileName);
-									}
-								}
-							});
-							itd->Unlock();
-							ViewList.SetCurName(FindItem->FindData.strFileName);
-
-							Dlg->SendMessage(DM_SHOWDIALOG, FALSE, nullptr);
-							Dlg->SendMessage(DM_ENABLEREDRAW, FALSE, nullptr);
-							{
-								auto ShellViewer = FileViewer::create(strSearchFileName, FALSE, FALSE, FALSE, -1, nullptr, (list_count > 1 ? &ViewList : nullptr));
-								ShellViewer->SetEnableF6(TRUE);
-
-								if(FindItem->Arc)
-								{
-									if(!(FindItem->Arc->Flags & OPIF_REALNAMES))
-									{
-										ShellViewer->SetSaveToSaveAs(true);
-									}
-								}
-								Global->WindowManager->ExecuteModal(ShellViewer);
-								// ��������� �������� �����
-								Global->WindowManager->ProcessKey(Manager::Key(KEY_CONSOLE_BUFFER_RESIZE));
-							}
-							Dlg->SendMessage(DM_ENABLEREDRAW, TRUE, nullptr);
-							Dlg->SendMessage(DM_SHOWDIALOG, TRUE, nullptr);
-						}
-						else
-						{
-							auto ShellEditor = FileEditor::create(strSearchFileName, CP_DEFAULT, 0);
-							ShellEditor->SetEnableF6(true);
-
-							if(FindItem->Arc)
-							{
-								if(!(FindItem->Arc->Flags & OPIF_REALNAMES))
-								{
-									ShellEditor->SetSaveToSaveAs(true);
-								}
-							}
-							auto editorExitCode=ShellEditor->GetExitCode();
-							if (editorExitCode != XC_OPEN_ERROR && editorExitCode != XC_LOADING_INTERRUPTED)
-							{
-								Global->WindowManager->ExecuteModal(ShellEditor);
-								// ��������� �������� �����
-								Global->WindowManager->ProcessKey(Manager::Key(KEY_CONSOLE_BUFFER_RESIZE));
-							}
-						}
-						Console().SetTitle(strOldTitle);
-					}
 					if (RemoveTemp)
 					{
 						DeleteFileWithFolder(strSearchFileName);
@@ -1906,8 +1861,96 @@
 	return Dlg->DefProc(Msg,Param1,Param2);
 }
 
-void FindFiles::AddMenuRecord(Dialog* Dlg,const string& FullName, const os::FAR_FIND_DATA& FindData, void* Data, FARPANELITEMFREECALLBACK FreeData)
+void FindFiles::OpenFile(string strSearchFileName, int openKey, const FindListItem* FindItem, Dialog* Dlg)
 {
+	if (!os::fs::exists(strSearchFileName))
+		return;
+	
+	FILETYPE_MODE openMode = FILETYPE_VIEW;
+	bool shouldForceInternal = false;
+	bool isKnownKey = GetFiletypeOpenMode(openKey, openMode, shouldForceInternal);
+	assert(isKnownKey); // ensure all possible keys are handled 
+
+	const auto strOldTitle = Console().GetTitle();
+
+	string shortFileName = ExtractFileName(strSearchFileName);
+	bool isProcessed = !shouldForceInternal && ProcessLocalFileTypes(strSearchFileName, shortFileName, openMode, PluginMode);
+
+	if (!isProcessed)
+	{
+		if (openMode == FILETYPE_ALTVIEW && Global->Opt->strExternalViewer.empty())
+			openMode = FILETYPE_VIEW;
+
+		if (openMode == FILETYPE_ALTEDIT && Global->Opt->strExternalEditor.empty())
+			openMode = FILETYPE_EDIT;
+
+		if (openMode == FILETYPE_VIEW)
+		{
+			NamesList ViewList;
+			int list_count = 0;
+
+			// ������ ��� ����, ������ ���� ������ �����...
+			itd->ForEachFindItem([&list_count, &ViewList](const FindListItem& i)
+			{
+				bool isRealName = !i.Arc || (i.Arc->Flags & OPIF_REALNAMES);
+				if (isRealName)
+				{
+					if (!i.FindData.strFileName.empty() && !(i.FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
+					{
+						++list_count;
+						ViewList.AddName(i.FindData.strFileName);
+					}
+				}
+			});
+
+			ViewList.SetCurName(FindItem->FindData.strFileName);
+
+			Dlg->SendMessage(DM_SHOWDIALOG, FALSE, nullptr);
+			Dlg->SendMessage(DM_ENABLEREDRAW, FALSE, nullptr);
+			{
+				auto ShellViewer = FileViewer::create(strSearchFileName, FALSE, FALSE, FALSE, -1, nullptr, (list_count > 1 ? &ViewList : nullptr));
+				ShellViewer->SetEnableF6(TRUE);
+
+				if (FindItem->Arc && !(FindItem->Arc->Flags & OPIF_REALNAMES))
+					ShellViewer->SetSaveToSaveAs(true);
+
+				Global->WindowManager->ExecuteModal(ShellViewer);
+				// ��������� �������� �����
+				Global->WindowManager->ProcessKey(Manager::Key(KEY_CONSOLE_BUFFER_RESIZE));
+			}
+			Dlg->SendMessage(DM_ENABLEREDRAW, TRUE, nullptr);
+			Dlg->SendMessage(DM_SHOWDIALOG, TRUE, nullptr);
+		}
+
+		if (openMode == FILETYPE_EDIT)
+		{
+			auto ShellEditor = FileEditor::create(strSearchFileName, CP_DEFAULT, 0);
+			ShellEditor->SetEnableF6(true);
+
+			if (FindItem->Arc && !(FindItem->Arc->Flags & OPIF_REALNAMES))
+				ShellEditor->SetSaveToSaveAs(true);
+
+			auto editorExitCode = ShellEditor->GetExitCode();
+			if (editorExitCode != XC_OPEN_ERROR && editorExitCode != XC_LOADING_INTERRUPTED)
+			{
+				Global->WindowManager->ExecuteModal(ShellEditor);
+				// ��������� �������� �����
+				Global->WindowManager->ProcessKey(Manager::Key(KEY_CONSOLE_BUFFER_RESIZE));
+			}
+		}
+
+		if (openMode == FILETYPE_ALTEDIT || openMode == FILETYPE_ALTVIEW)
+		{
+			string externalCommand = openMode == FILETYPE_ALTEDIT ? Global->Opt->strExternalEditor : Global->Opt->strExternalViewer;
+			ProcessExternal(externalCommand, strSearchFileName, shortFileName, PluginMode);
+		}
+	}
+
+	Console().SetTitle(strOldTitle);	
+}
+
+void FindFiles::AddMenuRecord(Dialog* Dlg, const string& FullName, const os::FAR_FIND_DATA& FindData, void* Data, FARPANELITEMFREECALLBACK FreeData)
+{
 	if (!Dlg)
 		return;
 
@@ -2726,30 +2769,22 @@
 			case FD_BUTTON_PANEL:
 			// ���������� ���������� �� �������� �����
 			{
-				itd->Lock();
-				size_t ListSize = itd->GetFindList().size();
 				std::vector<PluginPanelItem> PanelItems;
-				PanelItems.reserve(ListSize);
+				PanelItems.reserve(itd->GetFindListCount());
 
-				std::for_each(RANGE(itd->GetFindList(), i)
+				itd->ForEachFindItem([&PanelItems, this](FindListItem& i)
 				{
 					if (!i.FindData.strFileName.empty() && i.Used)
-					// �������� ������, ���� �� ������
 					{
+						// �������� ������, ���� �� ������
 						// �� �������� � ���������� ������� ������� �� ����� �� �� �����.
 						// ����� ���� ������ ����� �����.
-						bool IsArchive=false;
-						if(i.Arc)
-						{
-							if(!(i.Arc->Flags&OPIF_REALNAMES))
-							{
-								IsArchive=true;
-							}
-						}
+						bool IsArchive = i.Arc && !(i.Arc->Flags&OPIF_REALNAMES);
+
 						// �������� ����� ���� ��� ����� ������ ��� ����� ����� �������
 						if (IsArchive || (Global->Opt->FindOpt.FindFolders && !SearchHex) ||
-							    !(i.FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
-						{
+							!(i.FindData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
+						{							
 							if (IsArchive)
 							{
 								i.FindData.strFileName = i.Arc->strArcName;
@@ -2767,8 +2802,9 @@
 							}
 						}
 					}
+
 				});
-				itd->Unlock();
+
 				auto hNewPlugin=Global->CtrlObject->Plugins->OpenFindListPlugin(PanelItems.data(), PanelItems.size());
 
 				if (hNewPlugin)
Index: findfile.hpp
===================================================================
--- findfile.hpp	(revision 13359)
+++ findfile.hpp	(working copy)
@@ -54,6 +54,7 @@
 class InterThreadData;
 class filemasks;
 class FileFilter;
+struct FindListItem;
 
 class FindFiles: noncopyable
 {
@@ -74,7 +75,8 @@
 	bool LookForString(const string& Name);
 	bool IsFileIncluded(PluginPanelItem* FileItem, const string& FullName, DWORD FileAttr, const string &strDisplayName);
 	intptr_t FindDlgProc(Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2);
-	void AddMenuRecord(Dialog* Dlg,const string& FullName, const os::FAR_FIND_DATA& FindData, void* Data, FARPANELITEMFREECALLBACK FreeData);
+	void OpenFile(string strSearchFileName, int key, const FindListItem* FindItem, Dialog* Dlg);
+	void AddMenuRecord(Dialog* Dlg, const string& FullName, const os::FAR_FIND_DATA& FindData, void* Data, FARPANELITEMFREECALLBACK FreeData);
 	void AddMenuRecord(Dialog* Dlg,const string& FullName, PluginPanelItem& FindData);
 	void DoPreparePluginList(Dialog* Dlg, bool Internal);
 	void ArchiveSearch(Dialog* Dlg, const string& ArcName);

4eyes

2015-09-02 17:21

reporter   bugnote:0013819

Last edited: 2015-09-02 17:22

looks like I've somehow excluded FarEng.hlf.m4 from the patch... Will update it in a few hours.

DrKnS

2015-09-02 18:23

administrator   bugnote:0013820

4411

4eyes

2015-09-03 12:44

reporter   bugnote:0013823

Still needs improvement for emulated filesystems. On one of my PCs, when opening alternate editor while searching inside .zip, it managed to delete temporary file faster then alternate editor starts up.

4eyes

2015-10-01 23:44

reporter   bugnote:0013958

Last edited: 2015-10-01 23:46

Fixed: temporary files will be deleted on FindFile closing. This should give enough time for external editor to open temporary file.

Fix is attached as 'unicode_far_r13428_FindFileList_fix.patch'

4eyes

2015-10-01 23:45

reporter  

unicode_far_r13428_FindFileList_fix.patch (1,756 bytes)   
Index: findfile.cpp
===================================================================
--- findfile.cpp	(revision 13428)
+++ findfile.cpp	(working copy)
@@ -379,6 +379,16 @@
 	}
 };
 
+// RAII file deletion
+class DelayedDeleter : noncopyable
+{
+	std::wstring m_pathToDelete;
+
+public:
+	DelayedDeleter(const std::wstring pathToDelete) : m_pathToDelete(pathToDelete) {}
+	~DelayedDeleter() { DeleteFileWithFolder(m_pathToDelete); }
+};
+
 void FindFiles::InitInFileSearch()
 {
 	if (!InFileSearchInited && !strFindStr.empty())
@@ -1691,7 +1701,8 @@
 
 					if (RemoveTemp)
 					{
-						DeleteFileWithFolder(strSearchFileName);
+						// external editor may not have enough time to open this file, so deffer deletion
+						m_DelayedDeleters.emplace_back(strSearchFileName); 
 					}
 					return TRUE;
 				}
@@ -2956,7 +2967,8 @@
 	itd(std::make_unique<InterThreadData>()),
 	PauseEvent(Event::manual, Event::signaled),
 	StopEvent(Event::manual, Event::nonsignaled),
-	m_TimeCheck(time_check::immediate, GetRedrawTimeout())
+	m_TimeCheck(time_check::immediate, GetRedrawTimeout()),
+	m_DelayedDeleters()
 {
 	_ALGO(CleverSysLog clv(L"FindFiles::FindFiles()"));
 
Index: findfile.hpp
===================================================================
--- findfile.hpp	(revision 13428)
+++ findfile.hpp	(working copy)
@@ -55,6 +55,7 @@
 class filemasks;
 class FileFilter;
 struct FindListItem;
+class DelayedDeleter;
 
 class FindFiles: noncopyable
 {
@@ -128,6 +129,7 @@
 	std::unique_ptr<InterThreadData> itd;
 	struct CodePageInfo;
 	std::list<CodePageInfo> m_CodePages;
+	std::list<DelayedDeleter> m_DelayedDeleters;
 	CriticalSection PluginCS;
 	Event PauseEvent;
 	Event StopEvent;

DrKnS

2015-10-02 06:45

administrator   bugnote:0013959

4430.

Are you in our 'contributors' list already?

4eyes

2015-10-03 11:42

reporter   bugnote:0013961

> 4430
Build looks good, thanks.

> Are you in our 'contributors' list already?
No. My name is Victor Istomin.

Issue History

Date Modified Username Field Change
2015-09-02 09:09 4eyes New Issue
2015-09-02 09:09 4eyes File Added: unicode_far_r13359_FindFileList.patch
2015-09-02 17:19 DrKnS Assigned To => DrKnS
2015-09-02 17:19 DrKnS Status new => assigned
2015-09-02 17:21 4eyes Note Added: 0013819
2015-09-02 17:22 4eyes Note Edited: 0013819
2015-09-02 18:23 DrKnS Note Added: 0013820
2015-09-02 18:23 DrKnS Status assigned => feedback
2015-09-03 12:44 4eyes Note Added: 0013823
2015-09-03 12:44 4eyes Status feedback => assigned
2015-10-01 23:44 4eyes Note Added: 0013958
2015-10-01 23:45 4eyes File Added: unicode_far_r13428_FindFileList_fix.patch
2015-10-01 23:46 4eyes Note Edited: 0013958
2015-10-02 06:45 DrKnS Note Added: 0013959
2015-10-02 06:45 DrKnS Status assigned => feedback
2015-10-03 11:42 4eyes Note Added: 0013961
2015-10-03 11:42 4eyes Status feedback => assigned
2015-10-03 15:08 DrKnS Build => 4430
2015-10-03 15:08 DrKnS Status assigned => closed
2015-10-03 15:08 DrKnS Resolution open => fixed
2015-10-03 15:08 DrKnS Fixed in Version => 3.0