File indexing completed on 2024-05-26 17:06:05
0001 /* 0002 SPDX-FileCopyrightText: 2003-2004 Max Howell <max.howell@methylblue.com> 0003 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "builder.h" 0009 #include "Config.h" 0010 #include "widget.h" 0011 0012 // QtCore 0013 #include <QLocale> 0014 0015 #include <KI18n/KLocalizedString> 0016 0017 //**** REMOVE NEED FOR the +1 with MAX_RING_DEPTH uses 0018 //**** add some angle bounds checking (possibly in Segment ctor? can I delete in a ctor?) 0019 //**** this class is a mess 0020 0021 RadialMap::Builder::Builder(RadialMap::Map *m, const Directory *const d, bool fast) 0022 : m_map(m) 0023 , m_root(d) 0024 , m_minSize(static_cast<FileSize>(static_cast<long double>(d->size() * 3) / (PI * m->height() - m->MAP_2MARGIN))) 0025 , m_depth(&m->m_visibleDepth) 0026 { 0027 m_signature = new Chain<Segment>[*m_depth + 1]; 0028 0029 if (!fast) { //|| *m_depth == 0 ) //depth 0 is special case usability-wise //**** WHY?! 0030 // determine depth rather than use old one 0031 findVisibleDepth(d); // sets m_depth 0032 } 0033 0034 m_map->setRingBreadth(); 0035 setLimits(m_map->m_ringBreadth); 0036 build(d); 0037 0038 m_map->m_signature = m_signature; 0039 0040 delete[] m_limits; 0041 } 0042 0043 void RadialMap::Builder::findVisibleDepth(const Directory *const dir, const unsigned int depth) 0044 { 0045 //**** because I don't use the same minimumSize criteria as in the visual function 0046 // this can lead to incorrect visual representation 0047 //**** BUT, you can't set those limits until you know m_depth! 0048 0049 //**** also this function doesn't check to see if anything is actually visible 0050 // it just assumes that when it reaches a new level everything in it is visible 0051 // automatically. This isn't right especially as there might be no files in the 0052 // dir provided to this function! 0053 0054 static uint stopDepth = 0; 0055 0056 if (dir == m_root) { 0057 stopDepth = *m_depth; 0058 *m_depth = 0; 0059 } 0060 0061 if (*m_depth < depth) 0062 *m_depth = depth; 0063 if (*m_depth >= stopDepth) 0064 return; 0065 0066 for (ConstIterator<File> it = dir->constIterator(); it != dir->end(); ++it) 0067 if ((*it)->isDir() && (*it)->size() > m_minSize) 0068 findVisibleDepth(dynamic_cast<const Directory *>(*it), depth + 1); // if no files greater than min size the depth is still recorded 0069 } 0070 0071 void RadialMap::Builder::setLimits(const uint &b) // b = breadth? 0072 { 0073 long double size3 = m_root->size() * 3; 0074 long double pi2B = PI * 2 * b; 0075 0076 m_limits = new FileSize[*m_depth + 1]; // FIXME delete! 0077 0078 for (unsigned int d = 0; d <= *m_depth; ++d) 0079 m_limits[d] = static_cast<FileSize>(size3 / (pi2B * (d + 1))); // min is angle that gives 3px outer diameter for that depth 0080 } 0081 0082 //**** segments currently overlap at edges (i.e. end of first is start of next) 0083 bool RadialMap::Builder::build(const Directory *const dir, const unsigned int depth, unsigned int a_start, const unsigned int a_end) 0084 { 0085 // first iteration: dir == m_root 0086 0087 if (dir->fileCount() == 0) // we do fileCount rather than size to avoid chance of divide by zero later 0088 return false; 0089 0090 FileSize hiddenSize = 0; 0091 uint hiddenFileCount = 0; 0092 0093 for (ConstIterator<File> it = dir->constIterator(); it != dir->end(); ++it) { 0094 if ((*it)->size() > m_limits[depth]) { 0095 auto a_len = (unsigned int)(5760 * ((double)(*it)->size() / (double)m_root->size())); 0096 0097 auto *s = new Segment(*it, a_start, a_len); 0098 0099 (m_signature + depth)->append(s); 0100 0101 if ((*it)->isDir()) { 0102 if (depth != *m_depth) { 0103 // recurse 0104 s->m_hasHiddenChildren = build(dynamic_cast<const Directory *>(*it), depth + 1, a_start, a_start + a_len); 0105 } else 0106 s->m_hasHiddenChildren = true; 0107 } 0108 0109 a_start += a_len; //**** should we add 1? 0110 0111 } else { 0112 hiddenSize += (*it)->size(); 0113 0114 if ((*it)->isDir()) //**** considered virtual, but dir wouldn't count itself! 0115 hiddenFileCount += dynamic_cast<const Directory *>(*it)->fileCount(); // need to add one to count the dir as well 0116 0117 ++hiddenFileCount; 0118 } 0119 } 0120 0121 if (hiddenFileCount == dir->fileCount() && !Config::showSmallFiles) 0122 0123 return true; 0124 0125 else if ((Config::showSmallFiles && hiddenSize > m_limits[depth]) || (depth == 0 && (hiddenSize > dir->size() / 8)) /*|| > size() * 0.75*/) { 0126 // append a segment for unrepresented space - a "fake" segment 0127 0128 const QString s = i18np("%1 file: ~ %2", "%1 files: ~ %2", QLocale().toString(hiddenFileCount), File::humanReadableSize(hiddenSize / hiddenFileCount)); 0129 (m_signature + depth)->append(new Segment(new File(s, hiddenSize), a_start, a_end - a_start, true)); 0130 } 0131 0132 return false; 0133 }