annotate src/common.cpp @ 678:c0b46d0514a7 scale

Incomplete scaling updates. Should do this differently
author Chris Cannam
date Thu, 06 Dec 2018 14:55:45 +0000
parents f9b805d8cab4
children
rev   line source
Chris@57 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@57 2
Chris@57 3 /*
Chris@57 4 EasyMercurial
Chris@57 5
Chris@57 6 Based on HgExplorer by Jari Korhonen
Chris@57 7 Copyright (c) 2010 Jari Korhonen
Chris@644 8 Copyright (c) 2013 Chris Cannam
Chris@644 9 Copyright (c) 2013 Queen Mary, University of London
Chris@57 10
Chris@57 11 This program is free software; you can redistribute it and/or
Chris@57 12 modify it under the terms of the GNU General Public License as
Chris@57 13 published by the Free Software Foundation; either version 2 of the
Chris@57 14 License, or (at your option) any later version. See the file
Chris@57 15 COPYING included with this distribution for more information.
Chris@57 16 */
jtkorhonen@0 17
Chris@62 18 #include "common.h"
Chris@62 19 #include "debug.h"
jtkorhonen@0 20
Chris@62 21 #include <QFileInfo>
Chris@62 22 #include <QProcessEnvironment>
Chris@62 23 #include <QStringList>
Chris@77 24 #include <QDir>
Chris@172 25 #include <QRegExp>
Chris@678 26 #include <QFont>
Chris@678 27 #include <QFontMetrics>
jtkorhonen@0 28
Chris@62 29 #include <sys/types.h>
Chris@76 30
Chris@76 31 #ifdef Q_OS_WIN32
Chris@76 32 #define _WIN32_WINNT 0x0500
Chris@166 33 #define SECURITY_WIN32
Chris@76 34 #include <windows.h>
Chris@76 35 #include <security.h>
Chris@455 36 #include <process.h>
Chris@76 37 #else
Chris@78 38 #include <errno.h>
Chris@62 39 #include <pwd.h>
Chris@78 40 #include <unistd.h>
Chris@80 41 #include <sys/ioctl.h>
Chris@80 42 #include <sys/types.h>
Chris@80 43 #include <sys/stat.h>
Chris@80 44 #include <fcntl.h>
Chris@105 45 #include <signal.h>
Chris@443 46 #include <stdio.h>
Chris@76 47 #endif
Chris@62 48
Chris@172 49 QString findInPath(QString name, QString installPath, bool executableRequired)
Chris@62 50 {
Chris@77 51 bool found = false;
Chris@62 52 if (name != "") {
Chris@172 53 if (name[0] != '/'
Chris@172 54 #ifdef Q_OS_WIN32
Chris@178 55 && (QRegExp("^\\w:").indexIn(name) != 0)
Chris@172 56 #endif
Chris@178 57 ) {
Chris@77 58 #ifdef Q_OS_WIN32
Chris@77 59 QChar pathSep = ';';
Chris@77 60 #else
Chris@77 61 QChar pathSep = ':';
Chris@77 62 #endif
Chris@62 63 name = QFileInfo(name).fileName();
Chris@62 64 QString path =
Chris@62 65 QProcessEnvironment::systemEnvironment().value("PATH");
Chris@214 66 DEBUG << "findInPath: seeking location for binary " << name
Chris@74 67 << ": system path is " << path << endl;
Chris@172 68 if (installPath != "") {
Chris@214 69 DEBUG << "findInPath: install path is " << installPath
Chris@172 70 << ", adding to system path" << endl;
Chris@172 71 //!!! path = path + pathSep + installPath;
Chris@172 72 path = installPath + pathSep + path;
Chris@172 73 }
Chris@74 74 #ifndef Q_OS_WIN32
Chris@178 75 //!!!
Chris@74 76 path = path + ":/usr/local/bin";
Chris@74 77 DEBUG << "... adding /usr/local/bin just in case (fix and add settings dlg please)"
Chris@74 78 << endl;
Chris@74 79 #endif
Chris@62 80 QStringList elements = path.split(pathSep, QString::SkipEmptyParts);
Chris@62 81 foreach (QString element, elements) {
Chris@77 82 QString full = QDir(element).filePath(name);
Chris@62 83 QFileInfo fi(full);
Chris@214 84 DEBUG << "findInPath: looking at " << full << endl;
Chris@172 85 if (fi.exists() && fi.isFile()) {
Chris@214 86 DEBUG << "findInPath: it's a file" << endl;
Chris@172 87 if (!executableRequired || fi.isExecutable()) {
Chris@172 88 name = full;
Chris@214 89 DEBUG << "findInPath: found at " << name << endl;
Chris@172 90 found = true;
Chris@172 91 break;
Chris@172 92 }
Chris@62 93 }
Chris@62 94 }
Chris@214 95 } else {
Chris@214 96 // absolute path given
Chris@214 97 QFileInfo fi(name);
Chris@214 98 DEBUG << "findInPath: looking at absolute path " << name << endl;
Chris@214 99 if (fi.exists() && fi.isFile()) {
Chris@214 100 DEBUG << "findInPath: it's a file" << endl;
Chris@214 101 if (!executableRequired || fi.isExecutable()) {
Chris@214 102 DEBUG << "findInPath: found at " << name << endl;
Chris@214 103 found = true;
Chris@214 104 }
Chris@214 105 }
Chris@62 106 }
Chris@62 107 }
Chris@77 108 #ifdef Q_OS_WIN32
Chris@77 109 if (!found) {
Chris@77 110 if (!name.endsWith(".exe")) {
Chris@172 111 return findInPath(name + ".exe", installPath, executableRequired);
Chris@77 112 }
Chris@77 113 }
Chris@77 114 #endif
Chris@213 115 if (found) {
Chris@213 116 return name;
Chris@213 117 } else {
Chris@213 118 return "";
Chris@213 119 }
Chris@62 120 }
jtkorhonen@0 121
Chris@62 122 #ifdef Q_OS_WIN32
Chris@62 123 QString getUserRealName()
Chris@62 124 {
Chris@76 125 TCHAR buf[1024];
Chris@76 126 long unsigned int maxlen = 1000;
Chris@62 127 LPTSTR info = buf;
jtkorhonen@0 128
Chris@76 129 if (!GetUserNameEx(NameDisplay, info, &maxlen)) {
Chris@76 130 DEBUG << "GetUserNameEx failed: " << GetLastError() << endl;
Chris@62 131 return "";
Chris@62 132 }
jtkorhonen@0 133
Chris@76 134 #ifdef UNICODE
Chris@76 135 return QString::fromUtf16((const unsigned short *)info);
Chris@76 136 #else
Chris@76 137 return QString::fromLocal8Bit(info);
Chris@76 138 #endif
Chris@62 139 }
luisf@71 140 #else
luisf@71 141 #ifdef Q_OS_MAC
Chris@62 142 // Nothing here: definition is in common_osx.mm
Chris@62 143 #else
Chris@62 144 QString getUserRealName()
Chris@62 145 {
Chris@62 146 const int maxlen = 1023;
Chris@62 147 char buf[maxlen + 2];
jtkorhonen@0 148
Chris@62 149 if (getlogin_r(buf, maxlen)) return "";
jtkorhonen@0 150
Chris@62 151 struct passwd *p = getpwnam(buf);
Chris@62 152 if (!p) return "";
Chris@62 153
Chris@62 154 QString s(p->pw_gecos);
Chris@62 155 if (s != "") s = s.split(',')[0];
Chris@62 156 return s;
Chris@62 157 }
Chris@62 158 #endif
luisf@71 159 #endif
jtkorhonen@0 160
Chris@78 161 void loseControllingTerminal()
Chris@78 162 {
Chris@78 163 #ifndef Q_OS_WIN32
Chris@80 164
Chris@80 165 if (!isatty(0)) {
Chris@80 166 DEBUG << "stdin is not a terminal" << endl;
Chris@80 167 } else {
Chris@80 168 DEBUG << "stdin is a terminal, detaching from it" << endl;
Chris@80 169 if (ioctl(0, TIOCNOTTY, NULL) < 0) {
Chris@80 170 perror("ioctl failed");
Chris@83 171 DEBUG << "ioctl for TIOCNOTTY on stdin failed (errno = " << errno << ")" << endl;
Chris@78 172 } else {
Chris@83 173 DEBUG << "ioctl for TIOCNOTTY on stdin succeeded" << endl;
Chris@83 174 return;
Chris@78 175 }
Chris@80 176 }
Chris@80 177
Chris@80 178 int ttyfd = open("/dev/tty", O_RDWR);
Chris@80 179 if (ttyfd < 0) {
Chris@80 180 DEBUG << "failed to open controlling terminal" << endl;
Chris@80 181 } else {
Chris@80 182 if (ioctl(ttyfd, TIOCNOTTY, NULL) < 0) {
Chris@80 183 perror("ioctl failed");
Chris@83 184 DEBUG << "ioctl for TIOCNOTTY on controlling terminal failed (errno = " << errno << ")" << endl;
Chris@80 185 } else {
Chris@83 186 DEBUG << "ioctl for TIOCNOTTY on controlling terminal succeeded" << endl;
Chris@83 187 return;
Chris@78 188 }
Chris@78 189 }
Chris@80 190
Chris@78 191 #endif
Chris@78 192 }
Chris@79 193
Chris@105 194 void installSignalHandlers()
Chris@105 195 {
Chris@105 196 #ifndef Q_OS_WIN32
Chris@105 197 sigset_t sgnals;
Chris@105 198 sigemptyset (&sgnals);
Chris@105 199 sigaddset(&sgnals, SIGHUP);
Chris@105 200 sigaddset(&sgnals, SIGCONT);
Chris@105 201 pthread_sigmask(SIG_BLOCK, &sgnals, 0);
Chris@105 202 #endif
Chris@105 203 }
Chris@105 204
Chris@455 205 ProcessStatus
Chris@455 206 GetProcessStatus(int pid)
Chris@455 207 {
Chris@455 208 #ifdef _WIN32
Chris@455 209 HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
Chris@455 210 if (!handle) {
Chris@455 211 return ProcessNotRunning;
Chris@455 212 } else {
Chris@455 213 CloseHandle(handle);
Chris@455 214 return ProcessRunning;
Chris@455 215 }
Chris@455 216 #else
Chris@455 217 if (kill(getpid(), 0) == 0) {
Chris@455 218 if (kill(pid, 0) == 0) {
Chris@455 219 return ProcessRunning;
Chris@455 220 } else {
Chris@455 221 return ProcessNotRunning;
Chris@455 222 }
Chris@455 223 } else {
Chris@455 224 return UnknownProcessStatus;
Chris@455 225 }
Chris@455 226 #endif
Chris@455 227 }
Chris@455 228
Chris@79 229 FolderStatus getFolderStatus(QString path)
Chris@79 230 {
Chris@85 231 if (path != "/" && path.endsWith("/")) {
Chris@85 232 path = path.left(path.length()-1);
Chris@85 233 }
Chris@84 234 DEBUG << "getFolderStatus: " << path << endl;
Chris@79 235 QFileInfo fi(path);
Chris@79 236 if (fi.exists()) {
Chris@84 237 DEBUG << "exists" << endl;
Chris@79 238 QDir dir(path);
Chris@79 239 if (!dir.exists()) { // returns false for files
Chris@84 240 DEBUG << "not directory" << endl;
Chris@79 241 return FolderIsFile;
Chris@79 242 }
Chris@79 243 if (QDir(dir.filePath(".hg")).exists()) {
Chris@84 244 DEBUG << "has repo" << endl;
Chris@79 245 return FolderHasRepo;
Chris@79 246 }
Chris@79 247 return FolderExists;
Chris@79 248 } else {
Chris@79 249 QDir parent = fi.dir();
Chris@79 250 if (parent.exists()) {
Chris@84 251 DEBUG << "parent exists" << endl;
Chris@79 252 return FolderParentExists;
Chris@79 253 }
Chris@79 254 return FolderUnknown;
Chris@79 255 }
Chris@79 256 }
Chris@79 257
Chris@79 258 QString getContainingRepoFolder(QString path)
Chris@79 259 {
Chris@79 260 if (getFolderStatus(path) == FolderHasRepo) return "";
Chris@79 261
Chris@79 262 QFileInfo me(path);
Chris@79 263 QFileInfo parent(me.dir().absolutePath());
Chris@79 264
Chris@79 265 while (me != parent) {
Chris@79 266 QString parentPath = parent.filePath();
Chris@79 267 if (getFolderStatus(parentPath) == FolderHasRepo) {
Chris@79 268 return parentPath;
Chris@79 269 }
Chris@79 270 me = parent;
Chris@79 271 parent = me.dir().absolutePath();
Chris@79 272 }
Chris@79 273
Chris@79 274 return "";
Chris@79 275 }
Chris@79 276
Chris@79 277 QString xmlEncode(QString s)
Chris@79 278 {
Chris@79 279 s
Chris@79 280 .replace("&", "&amp;")
Chris@79 281 .replace("<", "&lt;")
Chris@79 282 .replace(">", "&gt;")
Chris@79 283 .replace("\"", "&quot;")
Chris@79 284 .replace("'", "&apos;");
Chris@79 285
Chris@79 286 return s;
Chris@79 287 }
Chris@408 288
Chris@408 289 QString uniDecode(QString s)
Chris@408 290 {
Chris@408 291 QString d;
Chris@408 292 for (int i = 0; i < s.length(); ++i) {
Chris@412 293 // backslash escaped with another backslash: replace with a
Chris@410 294 // single backslash and skip on
Chris@411 295 if (i+1 < s.length() && s[i] == '\\' && s[i+1] == '\\') {
Chris@411 296 d += '\\';
Chris@411 297 i += 1;
Chris@410 298 continue;
Chris@410 299 }
Chris@410 300 // unescaped backslash followed by u and at least four more
Chris@410 301 // chars: replace with Unicode character
Chris@408 302 if (i+5 < s.length() && s[i] == '\\' && s[i+1] == 'u') {
Chris@408 303 QString uni = s.mid(i+2, 4);
Chris@663 304 QByteArray ba = QByteArray::fromHex(uni.toLatin1());
Chris@408 305 d += QChar(ba[1], ba[0]);
Chris@408 306 i += 5;
Chris@410 307 continue;
Chris@408 308 }
Chris@410 309 // default case: leave alone
Chris@410 310 d += s[i];
Chris@408 311 }
Chris@408 312 return d;
Chris@408 313 }
Chris@443 314
Chris@443 315 QByteArray randomKey()
Chris@443 316 {
Chris@443 317 static int len = 16;
Chris@443 318
Chris@443 319 QByteArray ba;
Chris@443 320 ba.resize(len);
Chris@443 321 char *buffer = ba.data();
Chris@443 322
Chris@443 323 #ifdef Q_OS_WIN32
Chris@443 324
Chris@443 325 HCRYPTPROV provider = 0;
Chris@443 326 if (!CryptAcquireContextW(&provider, 0, 0,
Chris@443 327 PROV_RSA_FULL,
Chris@443 328 CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
Chris@443 329 return QByteArray();
Chris@443 330 }
Chris@443 331
chris@447 332 if (!CryptGenRandom(provider, len, (BYTE *)buffer)) {
Chris@443 333 CryptReleaseContext(provider, 0);
Chris@443 334 return QByteArray();
Chris@443 335 }
Chris@443 336
Chris@443 337 CryptReleaseContext(provider, 0);
Chris@443 338
Chris@443 339 #else
Chris@443 340
Chris@443 341 FILE *rf = fopen("/dev/urandom", "r");
Chris@443 342 if (!rf) {
Chris@443 343 return QByteArray();
Chris@443 344 }
Chris@443 345
Chris@443 346 for (int i = 0; i < len; ++i) {
Chris@443 347 buffer[i] = fgetc(rf);
Chris@443 348 }
Chris@443 349
Chris@443 350 fclose(rf);
Chris@443 351
Chris@443 352 #endif
Chris@443 353
Chris@443 354 return ba;
Chris@443 355 }
Chris@443 356
Chris@678 357 int
Chris@678 358 scalePixelSize(int pixels)
Chris@678 359 {
Chris@678 360 static double ratio = 0.0;
Chris@678 361 if (ratio == 0.0) {
Chris@678 362 double baseEm;
Chris@678 363 #ifdef Q_OS_MAC
Chris@678 364 baseEm = 17.0;
Chris@678 365 #else
Chris@678 366 baseEm = 15.0;
Chris@678 367 #endif
Chris@678 368 double em = QFontMetrics(QFont()).height();
Chris@678 369 ratio = em / baseEm;
Chris@678 370 }
Chris@678 371
Chris@678 372 int scaled = int(pixels * ratio + 0.5);
Chris@678 373 if (pixels != 0 && scaled == 0) scaled = 1;
Chris@678 374 return scaled;
Chris@678 375 }
Chris@678 376