Make System and Utils class based on QObject.
[maemo-rb.git] / rbutil / rbutilqt / base / utils.cpp
blobf9efd955f00b2d647f6f7f47fb230095ddd5b84d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "utils.h"
21 #include "rockboxinfo.h"
22 #include "system.h"
23 #include "rbsettings.h"
24 #include "systeminfo.h"
26 #ifdef UNICODE
27 #define _UNICODE
28 #endif
30 #include <QtCore>
31 #include <QDebug>
32 #include <cstdlib>
33 #include <stdio.h>
35 #if defined(Q_OS_WIN32)
36 #include <windows.h>
37 #include <tchar.h>
38 #include <winioctl.h>
39 #endif
40 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
41 #include <sys/statvfs.h>
42 #endif
44 // recursive function to delete a dir with files
45 bool Utils::recursiveRmdir( const QString &dirName )
47 QString dirN = dirName;
48 QDir dir(dirN);
49 // make list of entries in directory
50 QStringList list = dir.entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
51 QFileInfo fileInfo;
52 QString curItem, lstAt;
53 for(int i = 0; i < list.size(); i++){ // loop through all items of list
54 QString name = list.at(i);
55 curItem = dirN + "/" + name;
56 fileInfo.setFile(curItem);
57 if(fileInfo.isDir()) // is directory
58 recursiveRmdir(curItem); // call recRmdir() recursively for
59 // deleting subdirectory
60 else // is file
61 QFile::remove(curItem); // ok, delete file
63 dir.cdUp();
64 return dir.rmdir(dirN); // delete empty dir and return if (now empty)
65 // dir-removing was successfull
69 //! @brief resolves the given path, ignoring case.
70 //! @param path absolute path to resolve.
71 //! @return returns exact casing of path, empty string if path not found.
72 QString Utils::resolvePathCase(QString path)
74 QStringList elems;
75 QString realpath;
77 elems = path.split("/", QString::SkipEmptyParts);
78 int start;
79 #if defined(Q_OS_WIN32)
80 // on windows we must make sure to start with the first entry (i.e. the
81 // drive letter) instead of a single / to make resolving work.
82 start = 1;
83 realpath = elems.at(0) + "/";
84 #else
85 start = 0;
86 realpath = "/";
87 #endif
89 for(int i = start; i < elems.size(); i++) {
90 QStringList direlems
91 = QDir(realpath).entryList(QDir::AllEntries|QDir::Hidden|QDir::System);
92 if(direlems.contains(elems.at(i), Qt::CaseInsensitive)) {
93 // need to filter using QRegExp as QStringList::filter(QString)
94 // matches any substring
95 QString expr = QString("^" + elems.at(i) + "$");
96 QRegExp rx = QRegExp(expr, Qt::CaseInsensitive);
97 QStringList a = direlems.filter(rx);
99 if(a.size() != 1)
100 return QString("");
101 if(!realpath.endsWith("/"))
102 realpath += "/";
103 realpath += a.at(0);
105 else
106 return QString("");
108 qDebug() << "[Utils] resolving path" << path << "->" << realpath;
109 return realpath;
113 //! @brief figure the free disk space on a filesystem
114 //! @param path path on the filesystem to check
115 //! @return size in bytes
116 qulonglong Utils::filesystemFree(QString path)
118 qlonglong size = 0;
119 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
120 // the usage of statfs() is deprecated by the LSB so use statvfs().
121 struct statvfs fs;
122 int ret;
124 ret = statvfs(qPrintable(path), &fs);
126 if(ret == 0)
127 size = (qulonglong)fs.f_frsize * (qulonglong)fs.f_bavail;
128 #endif
129 #if defined(Q_OS_WIN32)
130 BOOL ret;
131 ULARGE_INTEGER freeAvailBytes;
133 ret = GetDiskFreeSpaceExW((LPCTSTR)path.utf16(), &freeAvailBytes, NULL, NULL);
134 if(ret)
135 size = freeAvailBytes.QuadPart;
136 #endif
137 return size;
140 //! \brief searches for a Executable in the Environement Path
141 QString Utils::findExecutable(QString name)
143 QString exepath;
144 //try autodetect tts
145 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
146 QStringList path = QString(getenv("PATH")).split(":", QString::SkipEmptyParts);
147 #elif defined(Q_OS_WIN)
148 QStringList path = QString(getenv("PATH")).split(";", QString::SkipEmptyParts);
149 #endif
150 qDebug() << "[Utils] system path:" << path;
151 for(int i = 0; i < path.size(); i++)
153 QString executable = QDir::fromNativeSeparators(path.at(i)) + "/" + name;
154 #if defined(Q_OS_WIN)
155 executable += ".exe";
156 QStringList ex = executable.split("\"", QString::SkipEmptyParts);
157 executable = ex.join("");
158 #endif
159 qDebug() << "[Utils] executable:" << executable;
160 if(QFileInfo(executable).isExecutable())
162 return QDir::toNativeSeparators(executable);
165 return "";
169 /** @brief checks different Enviroment things. Ask if user wants to continue.
170 * @param permission if it should check for permission
171 * @return string with error messages if problems occurred, empty strings if none.
173 QString Utils::checkEnvironment(bool permission)
175 QString text = "";
177 // check permission
178 if(permission)
180 #if defined(Q_OS_WIN32)
181 if(System::userPermissions() != System::ADMIN)
183 text += tr("<li>Permissions insufficient for bootloader "
184 "installation.\nAdministrator priviledges are necessary.</li>");
186 #endif
189 // Check TargetId
190 RockboxInfo rbinfo(RbSettings::value(RbSettings::Mountpoint).toString());
191 QString installed = rbinfo.target();
192 if(!installed.isEmpty() && installed !=
193 SystemInfo::value(SystemInfo::CurConfigureModel).toString())
195 text += tr("<li>Target mismatch detected.\n"
196 "Installed target: %1, selected target: %2.</li>")
197 .arg(installed, SystemInfo::value(SystemInfo::CurPlatformName).toString());
198 // FIXME: replace installed by human-friendly name
201 if(!text.isEmpty())
202 return tr("Problem detected:") + "<ul>" + text + "</ul>";
203 else
204 return text;
206 /** @brief Compare two version strings.
207 * @param s1 first version string
208 * @param s2 second version string
209 * @return 0 if strings identical, 1 if second is newer, -1 if first.
211 int Utils::compareVersionStrings(QString s1, QString s2)
213 QString a = s1.trimmed();
214 QString b = s2.trimmed();
215 qDebug() << "[Utils] comparing version strings" << a << "and" << b;
216 // if strings are identical return 0.
217 if(a.isEmpty())
218 return 1;
219 if(b.isEmpty())
220 return -1;
222 while(!a.isEmpty() || !b.isEmpty()) {
223 // trim all leading non-digits and non-dots (dots are removed afterwards)
224 a.remove(QRegExp("^[^\\d\\.]*"));
225 b.remove(QRegExp("^[^\\d\\.]*"));
227 // trim all trailing non-digits for conversion (QString::toInt()
228 // requires this). Copy strings first as replace() changes the string.
229 QString numa = a;
230 QString numb = b;
231 numa.remove(QRegExp("\\D+.*$"));
232 numb.remove(QRegExp("\\D+.*$"));
234 // convert to number
235 bool ok1, ok2;
236 int vala = numa.toUInt(&ok1);
237 int valb = numb.toUInt(&ok2);
238 // if none of the numbers converted successfully we're at trailing garbage.
239 if(!ok1 && !ok2)
240 break;
241 if(!ok1)
242 return 1;
243 if(!ok2)
244 return -1;
246 // if numbers mismatch we have a decision.
247 if(vala != valb)
248 return (vala > valb) ? -1 : 1;
250 // trim leading digits.
251 a.remove(QRegExp("^\\d*"));
252 b.remove(QRegExp("^\\d*"));
254 // if number is immediately followed by a character consider it as
255 // version addon (like 1.2.3b). In this case compare characters too.
256 QChar ltra;
257 QChar ltrb;
258 if(a.contains(QRegExp("^[a-zA-Z]")))
259 ltra = a.at(0);
260 if(b.contains(QRegExp("^[a-zA-Z]")))
261 ltrb = b.at(0);
262 if(ltra != ltrb)
263 return (ltra < ltrb) ? 1 : -1;
264 // both are identical or no addon characters, ignore.
265 // remove modifiers and following dot.
266 a.remove(QRegExp("^[a-zA-Z]*\\."));
267 b.remove(QRegExp("^[a-zA-Z]*\\."));
270 // no differences found.
271 return 0;