| 
									
										
										
										
											2015-02-12 23:16:25 +08:00
										 |  |  | // Aseprite
 | 
					
						
							|  |  |  | // Copyright (C) 2001-2015  David Capello
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software; you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License version 2 as
 | 
					
						
							|  |  |  | // published by the Free Software Foundation.
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #ifdef HAVE_CONFIG_H
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | #include "config.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ui/file_selector.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/app.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-29 05:01:32 +08:00
										 |  |  | #include "app/console.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/file/file.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | #include "app/find_widget.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/ini_file.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-29 05:01:32 +08:00
										 |  |  | #include "app/load_widget.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "app/modules/gfx.h"
 | 
					
						
							|  |  |  | #include "app/modules/gui.h"
 | 
					
						
							|  |  |  | #include "app/recent_files.h"
 | 
					
						
							|  |  |  | #include "app/ui/file_list.h"
 | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  | #include "app/ui/skin/button_icon_impl.h"
 | 
					
						
							|  |  |  | #include "app/ui/skin/skin_theme.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | #include "app/widget_loader.h"
 | 
					
						
							|  |  |  | #include "base/bind.h"
 | 
					
						
							| 
									
										
										
										
											2015-06-04 03:34:27 +08:00
										 |  |  | #include "base/convert_to.h"
 | 
					
						
							| 
									
										
										
										
											2014-09-22 03:49:59 +08:00
										 |  |  | #include "base/fs.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | #include "base/path.h"
 | 
					
						
							|  |  |  | #include "base/split_string.h"
 | 
					
						
							| 
									
										
										
										
											2014-06-29 05:01:32 +08:00
										 |  |  | #include "base/unique_ptr.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | #include "ui/ui.h"
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:20:44 +08:00
										 |  |  | #include "generated_new_folder_window.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | #include <cctype>
 | 
					
						
							| 
									
										
										
										
											2014-09-22 03:49:59 +08:00
										 |  |  | #include <cerrno>
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | #include <iterator>
 | 
					
						
							|  |  |  | #include <set>
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef MAX_PATH
 | 
					
						
							| 
									
										
										
										
											2014-09-22 03:49:59 +08:00
										 |  |  | #  define MAX_PATH 4096         // TODO this is needed for Linux, is it correct?
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | namespace app { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace app::skin; | 
					
						
							|  |  |  | using namespace ui; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | template<class Container> | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | class NullableIterator { | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | public: | 
					
						
							|  |  |  |   typedef typename Container::iterator iterator; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   NullableIterator() : m_isNull(true) { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void reset() { m_isNull = true; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool isNull() const { return m_isNull; } | 
					
						
							|  |  |  |   bool isValid() const { return !m_isNull; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   iterator getIterator() { | 
					
						
							|  |  |  |     ASSERT(!m_isNull); | 
					
						
							|  |  |  |     return m_iterator; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setIterator(const iterator& it) { | 
					
						
							|  |  |  |     m_isNull = false; | 
					
						
							|  |  |  |     m_iterator = it; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   bool m_isNull; | 
					
						
							|  |  |  |   typename Container::iterator m_iterator; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Variables used only to maintain the history of navigation.
 | 
					
						
							|  |  |  | static FileItemList* navigation_history = NULL; // Set of FileItems navigated
 | 
					
						
							|  |  |  | static NullableIterator<FileItemList> navigation_position; // Current position in the navigation history
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  | // This map acts like a temporal customization by the user when he/she
 | 
					
						
							|  |  |  | // wants to open files.  The key (first) is the real "showExtensions"
 | 
					
						
							|  |  |  | // parameter given to the FileSelector::show() function. The value
 | 
					
						
							|  |  |  | // (second) is the selected extension by the user. It's used only in
 | 
					
						
							|  |  |  | // FileSelector::Open type of dialogs.
 | 
					
						
							|  |  |  | static std::map<std::string, std::string> preferred_open_extensions; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | // Slot for App::Exit signal
 | 
					
						
							|  |  |  | static void on_exit_delete_navigation_history() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   delete navigation_history; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  | class CustomFileNameEntry : public ComboBox | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |   CustomFileNameEntry() | 
					
						
							|  |  |  |     : m_fileList(nullptr) { | 
					
						
							|  |  |  |     setEditable(true); | 
					
						
							|  |  |  |     getEntryWidget()->EntryChange.connect(&CustomFileNameEntry::onEntryChange, this); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   void setAssociatedFileList(FileList* fileList) { | 
					
						
							|  |  |  |     m_fileList = fileList; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2014-09-10 11:58:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |   void onEntryChange() { | 
					
						
							|  |  |  |     removeAllItems(); | 
					
						
							| 
									
										
										
										
											2014-09-10 11:58:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // String to be autocompleted
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |     std::string left_part = getEntryWidget()->getText(); | 
					
						
							|  |  |  |     closeListBox(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-10 11:58:25 +08:00
										 |  |  |     if (left_part.empty()) | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |     for (const IFileItem* child : m_fileList->getFileList()) { | 
					
						
							| 
									
										
										
										
											2014-09-10 11:58:25 +08:00
										 |  |  |       std::string child_name = child->getDisplayName(); | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |       std::string::const_iterator it1, it2; | 
					
						
							| 
									
										
										
										
											2014-09-10 11:58:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       for (it1 = child_name.begin(), it2 = left_part.begin(); | 
					
						
							|  |  |  |            it1 != child_name.end() && it2 != left_part.end(); | 
					
						
							|  |  |  |            ++it1, ++it2) { | 
					
						
							|  |  |  |         if (std::tolower(*it1) != std::tolower(*it2)) | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Is the pattern (left_part) in the child_name's beginning?
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |       if (it1 != child_name.end() && it2 == left_part.end()) | 
					
						
							|  |  |  |         addItem(child_name); | 
					
						
							| 
									
										
										
										
											2014-09-10 11:58:25 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (getItemCount() > 0) | 
					
						
							|  |  |  |       openListBox(); | 
					
						
							| 
									
										
										
										
											2014-09-10 11:58:25 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | private: | 
					
						
							|  |  |  |   FileList* m_fileList; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-04-04 07:31:02 +08:00
										 |  |  | class CustomFileNameItem : public ListItem | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   CustomFileNameItem(const char* text, IFileItem* fileItem) | 
					
						
							|  |  |  |     : ListItem(text) | 
					
						
							|  |  |  |     , m_fileItem(fileItem) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   IFileItem* getFileItem() { return m_fileItem; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   IFileItem* m_fileItem; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class CustomFolderNameItem : public ListItem | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   CustomFolderNameItem(const char* text) | 
					
						
							|  |  |  |     : ListItem(text) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  | // We have this dummy/hidden widget only to handle special navigation
 | 
					
						
							|  |  |  | // with arrow keys. In the past this code was in the same FileSelector
 | 
					
						
							|  |  |  | // itself, but there were problems adding that window as a message
 | 
					
						
							|  |  |  | // filter. Mainly there is a special combination of widgets
 | 
					
						
							|  |  |  | // (comboboxes) that need to filter Esc key (e.g. to close the
 | 
					
						
							|  |  |  | // combobox popup). And we cannot pre-add a filter that send that key
 | 
					
						
							|  |  |  | // to the Manager before it's processed by the combobox filter.
 | 
					
						
							|  |  |  | class ArrowNavigator : public Widget { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |   ArrowNavigator(FileSelector* filesel) | 
					
						
							|  |  |  |     : Widget(kGenericWidget) | 
					
						
							|  |  |  |     , m_filesel(filesel) { | 
					
						
							|  |  |  |     setVisible(false); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |   bool onProcessMessage(ui::Message* msg) override { | 
					
						
							|  |  |  |     switch (msg->type()) { | 
					
						
							|  |  |  |       case kOpenMessage: | 
					
						
							|  |  |  |         getManager()->addMessageFilter(kKeyDownMessage, this); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case kCloseMessage: | 
					
						
							|  |  |  |         getManager()->removeMessageFilter(kKeyDownMessage, this); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2015-05-07 03:47:43 +08:00
										 |  |  |       case kKeyDownMessage: { | 
					
						
							|  |  |  |         KeyMessage* keyMsg = static_cast<KeyMessage*>(msg); | 
					
						
							|  |  |  |         KeyScancode scancode = keyMsg->scancode(); | 
					
						
							|  |  |  |         int unicode = keyMsg->unicodeChar(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef __APPLE__
 | 
					
						
							|  |  |  |         bool up = (msg->cmdPressed() && scancode == kKeyUp); | 
					
						
							|  |  |  |         bool enter = (msg->cmdPressed() && scancode == kKeyDown); | 
					
						
							|  |  |  |         bool back = (msg->cmdPressed() && msg->shiftPressed() && unicode == '['); | 
					
						
							|  |  |  |         bool forward = (msg->cmdPressed() && msg->shiftPressed() && unicode == ']'); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         bool up = (msg->altPressed() && scancode == kKeyUp); | 
					
						
							|  |  |  |         bool enter = (msg->altPressed() && scancode == kKeyDown); | 
					
						
							|  |  |  |         bool back = (msg->altPressed() && scancode == kKeyLeft); | 
					
						
							|  |  |  |         bool forward = (msg->altPressed() && scancode == kKeyRight); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (up) { | 
					
						
							|  |  |  |           m_filesel->goUp(); | 
					
						
							|  |  |  |           return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (enter) { | 
					
						
							|  |  |  |           m_filesel->goInsideFolder(); | 
					
						
							|  |  |  |           return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (back) { | 
					
						
							|  |  |  |           m_filesel->goBack(); | 
					
						
							|  |  |  |           return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (forward) { | 
					
						
							|  |  |  |           m_filesel->goForward(); | 
					
						
							|  |  |  |           return true; | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2015-05-07 03:47:43 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |     return Widget::onProcessMessage(msg); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |   FileSelector* m_filesel; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 03:34:27 +08:00
										 |  |  | FileSelector::FileSelector(FileSelectorType type, FileSelectorDelegate* delegate) | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   : m_type(type) | 
					
						
							| 
									
										
										
										
											2015-06-04 03:34:27 +08:00
										 |  |  |   , m_delegate(delegate) | 
					
						
							| 
									
										
										
										
											2014-03-30 05:42:17 +08:00
										 |  |  |   , m_navigationLocked(false) | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |   SkinTheme* theme = SkinTheme::instance(); | 
					
						
							| 
									
										
										
										
											2015-06-04 03:34:27 +08:00
										 |  |  |   bool withResizeOptions = (delegate && delegate->hasResizeCombobox()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  |   addChild(new ArrowNavigator(this)); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   m_fileName = new CustomFileNameEntry; | 
					
						
							|  |  |  |   m_fileName->setFocusMagnet(true); | 
					
						
							|  |  |  |   fileNamePlaceholder()->addChild(m_fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   goBackButton()->setFocusStop(false); | 
					
						
							|  |  |  |   goForwardButton()->setFocusStop(false); | 
					
						
							|  |  |  |   goUpButton()->setFocusStop(false); | 
					
						
							|  |  |  |   newFolderButton()->setFocusStop(false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-05 06:38:52 +08:00
										 |  |  |   goBackButton()->setIconInterface( | 
					
						
							|  |  |  |     new ButtonIconImpl(theme->parts.comboboxArrowLeft(), | 
					
						
							|  |  |  |                        theme->parts.comboboxArrowLeftSelected(), | 
					
						
							|  |  |  |                        theme->parts.comboboxArrowLeftDisabled(), | 
					
						
							|  |  |  |                        CENTER | MIDDLE)); | 
					
						
							|  |  |  |   goForwardButton()->setIconInterface( | 
					
						
							|  |  |  |     new ButtonIconImpl(theme->parts.comboboxArrowRight(), | 
					
						
							|  |  |  |                        theme->parts.comboboxArrowRightSelected(), | 
					
						
							|  |  |  |                        theme->parts.comboboxArrowRightDisabled(), | 
					
						
							|  |  |  |                        CENTER | MIDDLE)); | 
					
						
							|  |  |  |   goUpButton()->setIconInterface( | 
					
						
							|  |  |  |     new ButtonIconImpl(theme->parts.comboboxArrowUp(), | 
					
						
							|  |  |  |                        theme->parts.comboboxArrowUpSelected(), | 
					
						
							|  |  |  |                        theme->parts.comboboxArrowUpDisabled(), | 
					
						
							|  |  |  |                        CENTER | MIDDLE)); | 
					
						
							|  |  |  |   newFolderButton()->setIconInterface( | 
					
						
							|  |  |  |     new ButtonIconImpl(theme->parts.newfolder(), | 
					
						
							|  |  |  |                        theme->parts.newfolderSelected(), | 
					
						
							|  |  |  |                        theme->parts.newfolder(), | 
					
						
							|  |  |  |                        CENTER | MIDDLE)); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   setup_mini_look(goBackButton()); | 
					
						
							|  |  |  |   setup_mini_look(goForwardButton()); | 
					
						
							|  |  |  |   setup_mini_look(goUpButton()); | 
					
						
							|  |  |  |   setup_mini_look(newFolderButton()); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   m_fileList = new FileList(); | 
					
						
							|  |  |  |   m_fileList->setId("fileview"); | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   fileView()->attachToView(m_fileList); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   m_fileName->setAssociatedFileList(m_fileList); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   goBackButton()->Click.connect(Bind<void>(&FileSelector::onGoBack, this)); | 
					
						
							|  |  |  |   goForwardButton()->Click.connect(Bind<void>(&FileSelector::onGoForward, this)); | 
					
						
							|  |  |  |   goUpButton()->Click.connect(Bind<void>(&FileSelector::onGoUp, this)); | 
					
						
							|  |  |  |   newFolderButton()->Click.connect(Bind<void>(&FileSelector::onNewFolder, this)); | 
					
						
							|  |  |  |   location()->CloseListBox.connect(Bind<void>(&FileSelector::onLocationCloseListBox, this)); | 
					
						
							|  |  |  |   fileType()->Change.connect(Bind<void>(&FileSelector::onFileTypeChange, this)); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   m_fileList->FileSelected.connect(Bind<void>(&FileSelector::onFileListFileSelected, this)); | 
					
						
							|  |  |  |   m_fileList->FileAccepted.connect(Bind<void>(&FileSelector::onFileListFileAccepted, this)); | 
					
						
							|  |  |  |   m_fileList->CurrentFolderChanged.connect(Bind<void>(&FileSelector::onFileListCurrentFolderChanged, this)); | 
					
						
							| 
									
										
										
										
											2015-06-04 03:34:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   resizeOptions()->setVisible(withResizeOptions); | 
					
						
							|  |  |  |   if (withResizeOptions) { | 
					
						
							|  |  |  |     resize()->setValue("1");    // 100% is default
 | 
					
						
							|  |  |  |     resize()->setValue(base::convert_to<std::string>(m_delegate->getResizeScale())); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-09-10 10:42:47 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  | void FileSelector::goBack() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   onGoBack(); | 
					
						
							| 
									
										
										
										
											2014-09-10 10:42:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  | void FileSelector::goForward() | 
					
						
							| 
									
										
										
										
											2014-09-10 10:42:47 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-07 03:27:45 +08:00
										 |  |  |   onGoForward(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::goUp() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   onGoUp(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::goInsideFolder() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (m_fileList->getSelectedFileItem() && | 
					
						
							|  |  |  |       m_fileList->getSelectedFileItem()->isBrowsable()) { | 
					
						
							|  |  |  |     m_fileList->setCurrentFolder( | 
					
						
							|  |  |  |       m_fileList->getSelectedFileItem()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 03:11:06 +08:00
										 |  |  | std::string FileSelector::show( | 
					
						
							|  |  |  |   const std::string& title, | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |   const std::string& initialPath, | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   const std::string& showExtensions) | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |   std::string result; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-24 19:51:59 +08:00
										 |  |  |   FileSystemModule* fs = FileSystemModule::instance(); | 
					
						
							|  |  |  |   LockFS lock(fs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fs->refresh(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (!navigation_history) { | 
					
						
							|  |  |  |     navigation_history = new FileItemList(); | 
					
						
							|  |  |  |     App::instance()->Exit.connect(&on_exit_delete_navigation_history); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // we have to find where the user should begin to browse files (start_folder)
 | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |   std::string start_folder_path; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   IFileItem* start_folder = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // If initialPath doesn't contain a path.
 | 
					
						
							|  |  |  |   if (base::get_file_path(initialPath).empty()) { | 
					
						
							|  |  |  |     // Get the saved `path' in the configuration file.
 | 
					
						
							| 
									
										
										
										
											2014-10-20 12:20:08 +08:00
										 |  |  |     std::string path = get_config_string("FileSelect", "CurrentDirectory", "<empty>"); | 
					
						
							|  |  |  |     if (path == "<empty>") { | 
					
						
							| 
									
										
										
										
											2014-09-22 03:49:59 +08:00
										 |  |  |       start_folder_path = base::get_user_docs_folder(); | 
					
						
							|  |  |  |       path = base::join_path(start_folder_path, initialPath); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-09-22 03:49:59 +08:00
										 |  |  |     start_folder = fs->getFileItemFromPath(path); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     // Remove the filename.
 | 
					
						
							|  |  |  |     start_folder_path = base::join_path(base::get_file_path(initialPath), ""); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   start_folder_path = base::fix_path_separators(start_folder_path); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!start_folder) | 
					
						
							| 
									
										
										
										
											2014-04-24 19:51:59 +08:00
										 |  |  |     start_folder = fs->getFileItemFromPath(start_folder_path); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   PRINTF("start_folder_path = %s (%p)\n", start_folder_path.c_str(), start_folder); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-01 01:17:49 +08:00
										 |  |  |   setMinSize(gfx::Size(ui::display_w()*9/10, ui::display_h()*9/10)); | 
					
						
							| 
									
										
										
										
											2013-01-11 23:43:25 +08:00
										 |  |  |   remapWindow(); | 
					
						
							|  |  |  |   centerWindow(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   // Change the file formats/extensions to be shown
 | 
					
						
							|  |  |  |   std::string initialExtension = base::get_file_extension(initialPath); | 
					
						
							|  |  |  |   std::string exts = showExtensions; | 
					
						
							| 
									
										
										
										
											2015-06-03 22:58:49 +08:00
										 |  |  |   if (m_type == FileSelectorType::Open) { | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |     auto it = preferred_open_extensions.find(exts); | 
					
						
							|  |  |  |     if (it == preferred_open_extensions.end()) | 
					
						
							|  |  |  |       exts = showExtensions; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |       exts = preferred_open_extensions[exts]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2015-06-03 22:58:49 +08:00
										 |  |  |     ASSERT(m_type == FileSelectorType::Save); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |     if (!initialExtension.empty()) | 
					
						
							|  |  |  |       exts = initialExtension; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   m_fileList->setExtensions(exts.c_str()); | 
					
						
							| 
									
										
										
										
											2012-07-18 09:12:41 +08:00
										 |  |  |   if (start_folder) | 
					
						
							|  |  |  |     m_fileList->setCurrentFolder(start_folder); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // current location
 | 
					
						
							|  |  |  |   navigation_position.reset(); | 
					
						
							|  |  |  |   addInNavigationHistory(m_fileList->getCurrentFolder()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // fill the location combo-box
 | 
					
						
							|  |  |  |   updateLocation(); | 
					
						
							|  |  |  |   updateNavigationButtons(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // fill file-type combo-box
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   fileType()->removeAllItems(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   // Get the default extension from the given initial file name
 | 
					
						
							|  |  |  |   m_defExtension = initialExtension; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // File type for all formats
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ListItem* item = new ListItem("All formats"); | 
					
						
							|  |  |  |     item->setValue(showExtensions); | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |     fileType()->addItem(item); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   } | 
					
						
							|  |  |  |   // One file type for each supported image format
 | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |   std::vector<std::string> tokens; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   base::split_string(showExtensions, tokens, ","); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   for (const auto& tok : tokens) { | 
					
						
							|  |  |  |     // If the default extension is empty, use the first filter
 | 
					
						
							|  |  |  |     if (m_defExtension.empty()) | 
					
						
							|  |  |  |       m_defExtension = tok; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ListItem* item = new ListItem(tok + " files"); | 
					
						
							|  |  |  |     item->setValue(tok); | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |     fileType()->addItem(item); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   } | 
					
						
							|  |  |  |   // All files
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ListItem* item = new ListItem("All files"); | 
					
						
							|  |  |  |     item->setValue("");         // Empty extensions means "*.*"
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |     fileType()->addItem(item); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // file name entry field
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |   m_fileName->setValue(base::get_file_name(initialPath).c_str()); | 
					
						
							|  |  |  |   m_fileName->getEntryWidget()->selectText(0, -1); | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   fileType()->setValue(exts); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // setup the title of the window
 | 
					
						
							|  |  |  |   setText(title.c_str()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // get the ok-button
 | 
					
						
							|  |  |  |   Widget* ok = this->findChild("ok"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // update the view
 | 
					
						
							|  |  |  |   View::getView(m_fileList)->updateView(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // open the window and run... the user press ok?
 | 
					
						
							|  |  |  | again: | 
					
						
							| 
									
										
										
										
											2012-07-09 10:24:42 +08:00
										 |  |  |   openWindowInForeground(); | 
					
						
							| 
									
										
										
										
											2013-01-11 23:43:25 +08:00
										 |  |  |   if (getKiller() == ok || | 
					
						
							|  |  |  |       getKiller() == m_fileList) { | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     // open the selected file
 | 
					
						
							|  |  |  |     IFileItem* folder = m_fileList->getCurrentFolder(); | 
					
						
							|  |  |  |     ASSERT(folder); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |     std::string fn = m_fileName->getValue(); | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |     std::string buf; | 
					
						
							| 
									
										
										
										
											2014-09-10 11:19:04 +08:00
										 |  |  |     IFileItem* enter_folder = NULL; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // up a level?
 | 
					
						
							|  |  |  |     if (fn == "..") { | 
					
						
							|  |  |  |       enter_folder = folder->getParent(); | 
					
						
							|  |  |  |       if (!enter_folder) | 
					
						
							|  |  |  |         enter_folder = folder; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-09-10 10:42:47 +08:00
										 |  |  |     else if (fn.empty()) { | 
					
						
							|  |  |  |       // show the window again
 | 
					
						
							|  |  |  |       setVisible(true); | 
					
						
							|  |  |  |       goto again; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |       // check if the user specified in "fn" a item of "fileview"
 | 
					
						
							|  |  |  |       const FileItemList& children = m_fileList->getFileList(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |       std::string fn2 = fn; | 
					
						
							| 
									
										
										
										
											2015-02-12 23:46:56 +08:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |       fn2 = base::string_to_lower(fn2); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-10 10:42:47 +08:00
										 |  |  |       for (IFileItem* child : children) { | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |         std::string child_name = child->getDisplayName(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-12 23:46:56 +08:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |         child_name = base::string_to_lower(child_name); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         if (child_name == fn2) { | 
					
						
							| 
									
										
										
										
											2014-09-10 10:42:47 +08:00
										 |  |  |           enter_folder = child; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |           buf = enter_folder->getFileName(); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!enter_folder) { | 
					
						
							|  |  |  |         // does the file-name entry have separators?
 | 
					
						
							|  |  |  |         if (base::is_path_separator(*fn.begin())) { // absolute path (UNIX style)
 | 
					
						
							| 
									
										
										
										
											2015-02-12 23:46:56 +08:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |           // get the drive of the current folder
 | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |           std::string drive = folder->getFileName(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |           if (drive.size() >= 2 && drive[1] == ':') { | 
					
						
							|  |  |  |             buf += drive[0]; | 
					
						
							|  |  |  |             buf += ':'; | 
					
						
							|  |  |  |             buf += fn; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             buf = base::join_path("C:", fn); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |           buf = fn; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2015-02-12 23:46:56 +08:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |         // does the file-name entry have colon?
 | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |         else if (fn.find(':') != std::string::npos) { // absolute path on Windows
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |           if (fn.size() == 2 && fn[1] == ':') { | 
					
						
							|  |  |  |             buf = base::join_path(fn, ""); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           else { | 
					
						
							|  |  |  |             buf = fn; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           buf = folder->getFileName(); | 
					
						
							|  |  |  |           buf = base::join_path(buf, fn); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         buf = base::fix_path_separators(buf); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // we can check if 'buf' is a folder, so we have to enter in it
 | 
					
						
							| 
									
										
										
										
											2014-04-24 19:51:59 +08:00
										 |  |  |         enter_folder = fs->getFileItemFromPath(buf); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // did we find a folder to enter?
 | 
					
						
							|  |  |  |     if (enter_folder && | 
					
						
							|  |  |  |         enter_folder->isFolder() && | 
					
						
							|  |  |  |         enter_folder->isBrowsable()) { | 
					
						
							|  |  |  |       // enter in the folder that was specified in the 'm_fileName'
 | 
					
						
							|  |  |  |       m_fileList->setCurrentFolder(enter_folder); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // clear the text of the entry widget
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |       m_fileName->setValue(""); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // show the window again
 | 
					
						
							|  |  |  |       setVisible(true); | 
					
						
							|  |  |  |       goto again; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // else file-name specified in the entry is really a file to open...
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // does it not have extension? ...we should add the extension
 | 
					
						
							|  |  |  |     // selected in the filetype combo-box
 | 
					
						
							|  |  |  |     if (base::get_file_extension(buf).empty()) { | 
					
						
							|  |  |  |       buf += '.'; | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |       buf += getSelectedExtension(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 22:58:49 +08:00
										 |  |  |     if (m_type == FileSelectorType::Save && base::is_file(buf)) { | 
					
						
							| 
									
										
										
										
											2015-05-29 03:11:06 +08:00
										 |  |  |       int ret = Alert::show("Warning<<File exists, overwrite it?<<%s||&Yes||&No||&Cancel", | 
					
						
							|  |  |  |                             base::get_file_name(buf).c_str()); | 
					
						
							|  |  |  |       if (ret == 2) { | 
					
						
							|  |  |  |         setVisible(true); | 
					
						
							|  |  |  |         goto again; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (ret == 1) { | 
					
						
							|  |  |  |         // Check for read-only attribute
 | 
					
						
							|  |  |  |         if (base::has_readonly_attr(buf)) { | 
					
						
							|  |  |  |           ui::Alert::show( | 
					
						
							|  |  |  |             "Problem<<The selected file is read-only. Try with other file.||&Go back"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           setVisible(true); | 
					
						
							|  |  |  |           goto again; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       // Cancel
 | 
					
						
							|  |  |  |       else if (ret != 1) { | 
					
						
							|  |  |  |         return ""; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     // duplicate the buffer to return a new string
 | 
					
						
							|  |  |  |     result = buf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // save the path in the configuration file
 | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |     std::string lastpath = folder->getKeyName(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     set_config_string("FileSelect", "CurrentDirectory", | 
					
						
							|  |  |  |                       lastpath.c_str()); | 
					
						
							| 
									
										
										
										
											2015-06-04 03:34:27 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_delegate && m_delegate->hasResizeCombobox()) { | 
					
						
							|  |  |  |       m_delegate->setResizeScale(base::convert_to<double>(resize()->getValue())); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Updates the content of the combo-box that shows the current
 | 
					
						
							|  |  |  | // location in the file-system.
 | 
					
						
							|  |  |  | void FileSelector::updateLocation() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   IFileItem* currentFolder = m_fileList->getCurrentFolder(); | 
					
						
							|  |  |  |   IFileItem* fileItem = currentFolder; | 
					
						
							| 
									
										
										
										
											2012-07-18 08:42:02 +08:00
										 |  |  |   std::list<IFileItem*> locations; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   int selected_index = -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (fileItem != NULL) { | 
					
						
							| 
									
										
										
										
											2012-07-18 08:42:02 +08:00
										 |  |  |     locations.push_front(fileItem); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     fileItem = fileItem->getParent(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Clear all the items from the combo-box
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   location()->removeAllItems(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Add item by item (from root to the specific current folder)
 | 
					
						
							|  |  |  |   int level = 0; | 
					
						
							| 
									
										
										
										
											2012-07-18 08:42:02 +08:00
										 |  |  |   for (std::list<IFileItem*>::iterator it=locations.begin(), end=locations.end(); | 
					
						
							|  |  |  |        it != end; ++it) { | 
					
						
							|  |  |  |     fileItem = *it; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Indentation
 | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |     std::string buf; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     for (int c=0; c<level; ++c) | 
					
						
							|  |  |  |       buf += "  "; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Location name
 | 
					
						
							|  |  |  |     buf += fileItem->getDisplayName(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Add the new location to the combo-box
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |     location()->addItem(new CustomFileNameItem(buf.c_str(), fileItem)); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (fileItem == currentFolder) | 
					
						
							|  |  |  |       selected_index = level; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     level++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Add paths from recent files list
 | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |     location()->addItem(""); | 
					
						
							|  |  |  |     location()->addItem("-------- Recent Paths --------"); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     RecentFiles::const_iterator it = App::instance()->getRecentFiles()->paths_begin(); | 
					
						
							|  |  |  |     RecentFiles::const_iterator end = App::instance()->getRecentFiles()->paths_end(); | 
					
						
							|  |  |  |     for (; it != end; ++it) | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |       location()->addItem(new CustomFolderNameItem(it->c_str())); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Select the location
 | 
					
						
							|  |  |  |   { | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |     location()->setSelectedItemIndex(selected_index); | 
					
						
							|  |  |  |     location()->getEntryWidget()->setText(currentFolder->getDisplayName().c_str()); | 
					
						
							|  |  |  |     location()->getEntryWidget()->deselectText(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::updateNavigationButtons() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   // Update the state of the go back button: if the navigation-history
 | 
					
						
							|  |  |  |   // has two elements and the navigation-position isn't the first one.
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   goBackButton()->setEnabled(navigation_history->size() > 1 && | 
					
						
							|  |  |  |                              (navigation_position.isNull() || | 
					
						
							|  |  |  |                               navigation_position.getIterator() != navigation_history->begin())); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Update the state of the go forward button: if the
 | 
					
						
							|  |  |  |   // navigation-history has two elements and the navigation-position
 | 
					
						
							|  |  |  |   // isn't the last one.
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   goForwardButton()->setEnabled(navigation_history->size() > 1 && | 
					
						
							|  |  |  |                                 (navigation_position.isNull() || | 
					
						
							|  |  |  |                                  navigation_position.getIterator() != navigation_history->end()-1)); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Update the state of the go up button: if the current-folder isn't
 | 
					
						
							|  |  |  |   // the root-item.
 | 
					
						
							|  |  |  |   IFileItem* currentFolder = m_fileList->getCurrentFolder(); | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   goUpButton()->setEnabled(currentFolder != FileSystemModule::instance()->getRootFileItem()); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::addInNavigationHistory(IFileItem* folder) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   ASSERT(folder != NULL); | 
					
						
							|  |  |  |   ASSERT(folder->isFolder()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Remove the history from the current position
 | 
					
						
							|  |  |  |   if (navigation_position.isValid()) { | 
					
						
							|  |  |  |     navigation_history->erase(navigation_position.getIterator()+1, navigation_history->end()); | 
					
						
							|  |  |  |     navigation_position.reset(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // If the history is empty or if the last item isn't the folder that
 | 
					
						
							|  |  |  |   // we are visiting...
 | 
					
						
							|  |  |  |   if (navigation_history->empty() || | 
					
						
							|  |  |  |       navigation_history->back() != folder) { | 
					
						
							|  |  |  |     // We can add the location in the history
 | 
					
						
							|  |  |  |     navigation_history->push_back(folder); | 
					
						
							|  |  |  |     navigation_position.setIterator(navigation_history->end()-1); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::onGoBack() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (navigation_history->size() > 1) { | 
					
						
							|  |  |  |     if (navigation_position.isNull()) | 
					
						
							|  |  |  |       navigation_position.setIterator(navigation_history->end()-1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (navigation_position.getIterator() != navigation_history->begin()) { | 
					
						
							|  |  |  |       navigation_position.setIterator(navigation_position.getIterator()-1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 05:00:19 +08:00
										 |  |  |       m_navigationLocked = true; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |       m_fileList->setCurrentFolder(*navigation_position.getIterator()); | 
					
						
							| 
									
										
										
										
											2014-03-30 05:00:19 +08:00
										 |  |  |       m_navigationLocked = false; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::onGoForward() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2012-07-18 08:42:02 +08:00
										 |  |  |   if (navigation_history->size() > 1) { | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     if (navigation_position.isNull()) | 
					
						
							|  |  |  |       navigation_position.setIterator(navigation_history->begin()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (navigation_position.getIterator() != navigation_history->end()-1) { | 
					
						
							|  |  |  |       navigation_position.setIterator(navigation_position.getIterator()+1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-30 05:00:19 +08:00
										 |  |  |       m_navigationLocked = true; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |       m_fileList->setCurrentFolder(*navigation_position.getIterator()); | 
					
						
							| 
									
										
										
										
											2014-03-30 05:00:19 +08:00
										 |  |  |       m_navigationLocked = false; | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::onGoUp() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   m_fileList->goUp(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-29 05:01:32 +08:00
										 |  |  | void FileSelector::onNewFolder() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-03 23:20:44 +08:00
										 |  |  |   app::gen::NewFolderWindow window; | 
					
						
							| 
									
										
										
										
											2014-06-29 05:01:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:20:44 +08:00
										 |  |  |   window.openWindowInForeground(); | 
					
						
							|  |  |  |   if (window.getKiller() == window.ok()) { | 
					
						
							| 
									
										
										
										
											2014-06-29 05:01:32 +08:00
										 |  |  |     IFileItem* currentFolder = m_fileList->getCurrentFolder(); | 
					
						
							|  |  |  |     if (currentFolder) { | 
					
						
							| 
									
										
										
										
											2015-06-03 23:20:44 +08:00
										 |  |  |       std::string dirname = window.name()->getText(); | 
					
						
							| 
									
										
										
										
											2014-06-29 05:01:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Create the new directory
 | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         currentFolder->createDirectory(dirname); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Enter in the new folder
 | 
					
						
							|  |  |  |         for (FileItemList::const_iterator it=currentFolder->getChildren().begin(), | 
					
						
							|  |  |  |                end=currentFolder->getChildren().end(); it != end; ++it) { | 
					
						
							|  |  |  |           if ((*it)->getDisplayName() == dirname) { | 
					
						
							|  |  |  |             m_fileList->setCurrentFolder(*it); | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       catch (const std::exception& e) { | 
					
						
							|  |  |  |         Console::showException(e); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | // Hook for the 'location' combo-box
 | 
					
						
							| 
									
										
										
										
											2014-03-30 05:42:17 +08:00
										 |  |  | void FileSelector::onLocationCloseListBox() | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | { | 
					
						
							|  |  |  |   // When the user change the location we have to set the
 | 
					
						
							|  |  |  |   // current-folder in the 'fileview' widget
 | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   CustomFileNameItem* comboFileItem = dynamic_cast<CustomFileNameItem*>(location()->getSelectedItem()); | 
					
						
							| 
									
										
										
										
											2013-04-04 07:31:02 +08:00
										 |  |  |   IFileItem* fileItem = (comboFileItem != NULL ? comboFileItem->getFileItem(): NULL); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Maybe the user selected a recent file path
 | 
					
						
							|  |  |  |   if (fileItem == NULL) { | 
					
						
							| 
									
										
										
										
											2013-04-04 07:31:02 +08:00
										 |  |  |     CustomFolderNameItem* comboFolderItem = | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |       dynamic_cast<CustomFolderNameItem*>(location()->getSelectedItem()); | 
					
						
							| 
									
										
										
										
											2013-04-04 07:31:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (comboFolderItem != NULL) { | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |       std::string path = comboFolderItem->getText(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |       fileItem = FileSystemModule::instance()->getFileItemFromPath(path); | 
					
						
							| 
									
										
										
										
											2013-04-04 07:31:02 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fileItem != NULL) { | 
					
						
							|  |  |  |     m_fileList->setCurrentFolder(fileItem); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Refocus the 'fileview' (the focus in that widget is more
 | 
					
						
							|  |  |  |     // useful for the user)
 | 
					
						
							|  |  |  |     getManager()->setFocus(m_fileList); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // When the user selects a new file-type (extension), we have to
 | 
					
						
							|  |  |  | // change the file-extension in the 'filename' entry widget
 | 
					
						
							|  |  |  | void FileSelector::onFileTypeChange() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   std::string exts = fileType()->getValue(); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   if (exts != m_fileList->extensions()) { | 
					
						
							|  |  |  |     m_navigationLocked = true; | 
					
						
							|  |  |  |     m_fileList->setExtensions(exts.c_str()); | 
					
						
							|  |  |  |     m_navigationLocked = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 22:58:49 +08:00
										 |  |  |     if (m_type == FileSelectorType::Open) { | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |       std::string origShowExtensions = fileType()->getItem(0)->getValue(); | 
					
						
							|  |  |  |       preferred_open_extensions[origShowExtensions] = fileType()->getValue(); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 22:58:49 +08:00
										 |  |  |   if (m_type == FileSelectorType::Save) { | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |     std::string newExtension = getSelectedExtension(); | 
					
						
							|  |  |  |     std::string fileName = m_fileName->getValue(); | 
					
						
							|  |  |  |     std::string currentExtension = base::get_file_extension(fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!currentExtension.empty()) | 
					
						
							|  |  |  |       m_fileName->setValue((fileName.substr(0, fileName.size()-currentExtension.size())+newExtension).c_str()); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::onFileListFileSelected() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   IFileItem* fileitem = m_fileList->getSelectedFileItem(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!fileitem->isFolder()) { | 
					
						
							| 
									
										
										
										
											2014-04-21 06:53:27 +08:00
										 |  |  |     std::string filename = base::get_file_name(fileitem->getFileName()); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-05 01:58:24 +08:00
										 |  |  |     m_fileName->setValue(filename.c_str()); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::onFileListFileAccepted() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   closeWindow(m_fileList); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void FileSelector::onFileListCurrentFolderChanged() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-30 05:00:19 +08:00
										 |  |  |   if (!m_navigationLocked) | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  |     addInNavigationHistory(m_fileList->getCurrentFolder()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateLocation(); | 
					
						
							|  |  |  |   updateNavigationButtons(); | 
					
						
							| 
									
										
										
										
											2015-05-07 03:58:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Close the autocomplete popup just in case it's open.
 | 
					
						
							|  |  |  |   m_fileName->closeListBox(); | 
					
						
							| 
									
										
										
										
											2012-06-16 10:37:59 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  | std::string FileSelector::getSelectedExtension() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-06-03 23:16:25 +08:00
										 |  |  |   std::string ext = fileType()->getValue(); | 
					
						
							| 
									
										
										
										
											2015-05-29 05:59:12 +08:00
										 |  |  |   if (ext.empty() || ext.find(',') != std::string::npos) | 
					
						
							|  |  |  |     ext = m_defExtension; | 
					
						
							|  |  |  |   return ext; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-06 08:20:19 +08:00
										 |  |  | } // namespace app
 |