diff --git a/util/path.h b/util/path.h --- a/util/path.h +++ b/util/path.h @@ -318,10 +318,22 @@ * @return the path pointing to the parent folder of this path. * * @sa KIO::upUrl() + * @sa ancestor(unsigned) */ Path parent() const; /** + * @return the ancestor path obtained by going up @p steps steps. + * + * If @p steps is larger than the number of segments, a path to root is + * returned. The returned path is always remote if this path is remote. + * + * @sa KIO::upUrl() + * @sa parent() + */ + Path ancestor(unsigned steps) const; + + /** * @return true when this path has a parent and false if this is a root or invalid path. */ bool hasParent() const; diff --git a/util/path.cpp b/util/path.cpp --- a/util/path.cpp +++ b/util/path.cpp @@ -430,21 +430,31 @@ Path Path::parent() const { + return ancestor(1); +} + +Path Path::ancestor(unsigned steps) const +{ if (m_data.isEmpty()) { - return Path(); + return {}; } Path ret(*this); - if (m_data.size() == (1 + (isRemote() ? 1 : 0))) { + unsigned remoteLen = isRemote() ? 1 : 0; + + if (m_data.size() <= remoteLen + steps) { + ret.m_data.resize(remoteLen + 1); + // keep the root item, but clear it, otherwise we'd make the path invalid // or a URL a local path auto& root = ret.m_data.last(); if (!isWindowsDriveLetter(root)) { root.clear(); } } else { - ret.m_data.pop_back(); + ret.m_data.erase(ret.m_data.end() - steps, ret.m_data.end()); } + return ret; }