Root/src/selector.cpp

Source at commit 7b10f9448bb9965e94f9a37a59f0999e9c51e68f created 5 years 4 months ago.
By Maarten ter Huurne, Suppress Clang analyzer warnings about dead assignments
1/***************************************************************************
2 * Copyright (C) 2006 by Massimiliano Torromeo *
3 * massimiliano.torromeo@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21#include "selector.h"
22
23#include "debug.h"
24#include "filelister.h"
25#include "gmenu2x.h"
26#include "linkapp.h"
27#include "menu.h"
28#include "surface.h"
29#include "utilities.h"
30
31#include <SDL.h>
32#include <algorithm>
33
34//for browsing the filesystem
35#include <sys/stat.h>
36#include <sys/types.h>
37#include <dirent.h>
38#include <fstream>
39
40using namespace std;
41
42Selector::Selector(GMenu2X& gmenu2x, LinkApp& link, const string &selectorDir)
43    : Dialog(gmenu2x)
44    , link(link)
45{
46    dir = selectorDir.empty() ? link.getSelectorDir() : selectorDir;
47    if (dir[dir.length()-1]!='/') dir += "/";
48}
49
50int Selector::exec(int startSelection) {
51    const bool showDirectories = link.getSelectorBrowser();
52
53    FileLister fl;
54    fl.setShowDirectories(showDirectories);
55    fl.setFilter(link.getSelectorFilter());
56    while (!prepare(fl) && showDirectories && dir != "/") {
57        // The given directory could not be opened; try parent.
58        dir = parentDir(dir);
59    }
60
61    OffscreenSurface bg(*gmenu2x.bg);
62    drawTitleIcon(bg, link.getIconPath(), true);
63    writeTitle(bg, link.getTitle());
64    writeSubTitle(bg, link.getDescription());
65
66    int x = 5;
67    if (fl.size() != 0) {
68        x = gmenu2x.drawButton(bg, "accept", gmenu2x.tr["Select"], x);
69    }
70    if (showDirectories) {
71        x = gmenu2x.drawButton(bg, "left", "", x);
72        x = gmenu2x.drawButton(bg, "cancel", gmenu2x.tr["Up one folder"], x);
73    } else {
74        x = gmenu2x.drawButton(bg, "cancel", "", x);
75    }
76    x = gmenu2x.drawButton(bg, "start", gmenu2x.tr["Exit"], x);
77    (void)x;
78
79    unsigned int top, height;
80    tie(top, height) = gmenu2x.getContentArea();
81
82    auto folderIcon = gmenu2x.sc.skinRes("imgs/folder.png");
83
84    // Figure out how many items we can fit in the content area.
85    int lineHeight = gmenu2x.font->getLineSpacing();
86    if (showDirectories && folderIcon) {
87        lineHeight = max(lineHeight, folderIcon->height() + 2);
88    }
89    unsigned int nb_elements = max(height / lineHeight, 1u);
90    // Redistribute any leftover space.
91    lineHeight = height / nb_elements;
92    top += (height - lineHeight * nb_elements) / 2;
93
94    bg.convertToDisplayFormat();
95
96    unsigned int firstElement = 0;
97    unsigned int selected = constrain(startSelection, 0, fl.size() - 1);
98
99    bool close = false, result = true;
100    while (!close) {
101        OutputSurface& s = *gmenu2x.s;
102
103        bg.blit(s, 0, 0);
104
105        if (fl.size() == 0) {
106            gmenu2x.font->write(s, "(" + gmenu2x.tr["no items"] + ")",
107                    4, top + lineHeight / 2,
108                    Font::HAlignLeft, Font::VAlignMiddle);
109        } else {
110            if (selected >= firstElement + nb_elements)
111                firstElement = selected - nb_elements + 1;
112            if (selected < firstElement)
113                firstElement = selected;
114
115            //Screenshot
116            if (fl.isFile(selected)) {
117                string path = screendir + trimExtension(fl[selected]) + ".png";
118                auto screenshot = OffscreenSurface::loadImage(path, false);
119                if (screenshot) {
120                    screenshot->blitRight(s, 320, 0, 320, 240, 128u);
121                }
122            }
123
124            //Selection
125            int iY = top + (selected - firstElement) * lineHeight;
126            if (selected<fl.size())
127                s.box(1, iY, 309, lineHeight, gmenu2x.skinConfColors[COLOR_SELECTION_BG]);
128
129            //Files & Dirs
130            s.setClipRect(0, top, 311, height);
131            for (unsigned int i = firstElement;
132                    i < fl.size() && i < firstElement + nb_elements; i++) {
133                iY = top + (i - firstElement) * lineHeight;
134                x = 4;
135                if (fl.isDirectory(i)) {
136                    if (folderIcon) {
137                        folderIcon->blit(s,
138                                x, iY + (lineHeight - folderIcon->height()) / 2);
139                        x += folderIcon->width() + 2;
140                    }
141                    gmenu2x.font->write(s, fl[i],
142                            x, iY + lineHeight / 2,
143                            Font::HAlignLeft, Font::VAlignMiddle);
144                } else {
145                    gmenu2x.font->write(s, trimExtension(fl[i]),
146                            x, iY + lineHeight / 2,
147                            Font::HAlignLeft, Font::VAlignMiddle);
148                }
149            }
150            s.clearClipRect();
151        }
152
153        gmenu2x.drawScrollBar(nb_elements, fl.size(), firstElement);
154        s.flip();
155
156        switch (gmenu2x.input.waitForPressedButton()) {
157            case InputManager::SETTINGS:
158                close = true;
159                result = false;
160                break;
161
162            case InputManager::UP:
163                if (selected == 0) selected = fl.size() -1;
164                else selected -= 1;
165                break;
166
167            case InputManager::ALTLEFT:
168                if ((int)(selected - nb_elements + 1) < 0)
169                    selected = 0;
170                else
171                    selected -= nb_elements - 1;
172                break;
173
174            case InputManager::DOWN:
175                if (selected+1>=fl.size()) selected = 0;
176                else selected += 1;
177                break;
178
179            case InputManager::ALTRIGHT:
180                if (selected + nb_elements - 1 >= fl.size())
181                    selected = fl.size() - 1;
182                else
183                    selected += nb_elements - 1;
184                break;
185
186            case InputManager::CANCEL:
187                if (!showDirectories) {
188                    close = true;
189                    result = false;
190                    break;
191                }
192                // ...fall through...
193            case InputManager::LEFT:
194                if (showDirectories) {
195                    selected = goToParentDir(fl);
196                    firstElement = 0;
197                }
198                break;
199
200            case InputManager::ACCEPT:
201                if (fl.size() != 0) {
202                    if (fl.isFile(selected)) {
203                        file = fl[selected];
204                        close = true;
205                    } else {
206                        string subdir = fl[selected];
207                        if (subdir == "..") {
208                            selected = goToParentDir(fl);
209                        } else {
210                            dir += subdir + '/';
211                            prepare(fl);
212                            selected = 0;
213                        }
214                        firstElement = 0;
215                    }
216                }
217                break;
218
219            default:
220                break;
221        }
222    }
223
224    return result ? (int)selected : -1;
225}
226
227bool Selector::prepare(FileLister& fl) {
228    bool opened = fl.browse(dir);
229
230    screendir = dir;
231    if (!screendir.empty() && screendir[screendir.length() - 1] != '/') {
232        screendir += "/";
233    }
234    screendir += "previews/";
235
236    return opened;
237}
238
239int Selector::goToParentDir(FileLister& fl) {
240    string oldDir = dir;
241    dir = parentDir(dir);
242    prepare(fl);
243    string oldName = oldDir.substr(dir.size(), oldDir.size() - dir.size() - 1);
244    auto& subdirs = fl.getDirectories();
245    auto it = find(subdirs.begin(), subdirs.end(), oldName);
246    return it == subdirs.end() ? 0 : it - subdirs.begin();
247}
248

Archive Download this file



interactive