1 | // SuperTux |
2 | // Copyright (C) 2016 Hume2 <teratux.mail@gmail.com> |
3 | // |
4 | // This program is free software: you can redistribute it and/or modify |
5 | // it under the terms of the GNU General Public License as published by |
6 | // the Free Software Foundation, either version 3 of the License, or |
7 | // (at your option) any later version. |
8 | // |
9 | // This program is distributed in the hope that it will be useful, |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | // GNU General Public License for more details. |
13 | // |
14 | // You should have received a copy of the GNU General Public License |
15 | // along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | #include "gui/menu_filesystem.hpp" |
18 | |
19 | #include <physfs.h> |
20 | |
21 | #include "addon/addon_manager.hpp" |
22 | #include "gui/menu_item.hpp" |
23 | #include "gui/menu_manager.hpp" |
24 | #include "physfs/util.hpp" |
25 | #include "util/file_system.hpp" |
26 | #include "util/log.hpp" |
27 | #include "util/gettext.hpp" |
28 | #include "util/string_util.hpp" |
29 | |
30 | FileSystemMenu::(std::string* filename, const std::vector<std::string>& extensions, |
31 | const std::string& basedir) : |
32 | m_filename(filename), |
33 | // when a basedir is given, 'filename' is relative to basedir, so |
34 | // it's useless as a starting point |
35 | m_directory(basedir.empty() ? FileSystem::dirname(*filename) : basedir), |
36 | m_extensions(extensions), |
37 | m_basedir(basedir), |
38 | m_directories(), |
39 | m_files() |
40 | { |
41 | AddonManager::current()->unmount_old_addons(); |
42 | |
43 | if (!PHYSFS_exists(m_directory.c_str())) { |
44 | m_directory = "/" ; //The filename is probably included in an old add-on. |
45 | } |
46 | |
47 | refresh_items(); |
48 | } |
49 | |
50 | FileSystemMenu::() |
51 | { |
52 | AddonManager::current()->mount_old_addons(); |
53 | } |
54 | |
55 | void |
56 | FileSystemMenu::() |
57 | { |
58 | m_items.clear(); |
59 | m_directories.clear(); |
60 | m_files.clear(); |
61 | m_directory = FileSystem::normalize(m_directory); |
62 | |
63 | add_label(m_directory); |
64 | add_hl(); |
65 | |
66 | int item_id = 0; |
67 | |
68 | // Do not allow leaving the data directory |
69 | if (m_directory != "/" ) { |
70 | m_directories.push_back(".." ); |
71 | } |
72 | |
73 | char** dir_files = PHYSFS_enumerateFiles(m_directory.c_str()); |
74 | if (dir_files) |
75 | { |
76 | for (const char* const* file = dir_files; *file != nullptr; ++file) |
77 | { |
78 | std::string filepath = FileSystem::join(m_directory, *file); |
79 | if (physfsutil::is_directory(filepath)) |
80 | { |
81 | m_directories.push_back(*file); |
82 | } |
83 | else |
84 | { |
85 | if (AddonManager::current()->is_from_old_addon(filepath)) { |
86 | continue; |
87 | } |
88 | |
89 | if (has_right_suffix(*file)) |
90 | { |
91 | m_files.push_back(*file); |
92 | } |
93 | } |
94 | } |
95 | PHYSFS_freeList(dir_files); |
96 | } |
97 | |
98 | for (const auto& item : m_directories) |
99 | { |
100 | add_entry(item_id, "[" + std::string(item) + "]" ); |
101 | item_id++; |
102 | } |
103 | |
104 | for (const auto& item : m_files) |
105 | { |
106 | add_entry(item_id, item); |
107 | item_id++; |
108 | } |
109 | |
110 | add_hl(); |
111 | add_back(_("Cancel" )); |
112 | |
113 | m_active_item = 2; |
114 | |
115 | // Re-center menu |
116 | on_window_resize(); |
117 | } |
118 | |
119 | bool |
120 | FileSystemMenu::(const std::string& file) const |
121 | { |
122 | for (const auto& extension : m_extensions) { |
123 | if (StringUtil::has_suffix(file, extension)) |
124 | { |
125 | return true; |
126 | } |
127 | } |
128 | return false; |
129 | } |
130 | |
131 | void |
132 | FileSystemMenu::(MenuItem& item) |
133 | { |
134 | if (item.get_id() >= 0) { |
135 | size_t id = item.get_id(); |
136 | if (id < m_directories.size()) { |
137 | m_directory = FileSystem::join(m_directory, m_directories[id]); |
138 | refresh_items(); |
139 | } else { |
140 | id -= m_directories.size(); |
141 | if (id < m_files.size()) { |
142 | std::string new_filename = FileSystem::join(m_directory, m_files[id]); |
143 | |
144 | if (!m_basedir.empty()) { |
145 | new_filename = FileSystem::relpath(new_filename, m_basedir); |
146 | } |
147 | |
148 | *m_filename = new_filename; |
149 | |
150 | MenuManager::instance().pop_menu(); |
151 | } else { |
152 | log_warning << "Selected invalid file or directory" << std::endl; |
153 | } |
154 | } |
155 | } |
156 | } |
157 | |
158 | /* EOF */ |
159 | |