Highlight graph of selected commit.
[qgit4.git] / src / common.h
blobf36634c62407db73c1e1d9168b2c3a978ae6636c
1 /*
2 Author: Marco Costalba (C) 2005-2007
4 Copyright: See COPYING file that comes with this distribution
6 */
7 #ifndef COMMON_H
8 #define COMMON_H
10 #include <QColor>
11 #include <QEvent>
12 #include <QFont>
13 #include <QHash>
14 #include <QLatin1String>
15 #include <QVariant>
16 #include <QVector>
19 QVariant does not support size_t type used in Qt containers, this is
20 a problem on 64bit systems where size_t != uint and when using debug
21 macros on size_t variables, as example dbg(vector.count()), a compile
22 error occurs.
23 Workaround this using a function template and a specialization.
24 Function _valueOf() is used by debug macros
26 template<typename T> inline const QString _valueOf(const T& x) { return QVariant(x).toString(); }
27 template<> inline const QString _valueOf(const QStringList& x) { return x.join(" "); }
28 inline const QString& _valueOf(const QString& x) { return x; }
29 inline const QString _valueOf(size_t x) { return QString::number((uint)x); }
31 // some debug macros
32 #define dbg(x) qDebug(#x " is <%s>", _valueOf(x).toLatin1().constData())
33 #define dbs(x) qDebug(_valueOf(x).toLatin1().constData())
34 #define dbp(s, x) qDebug(QString(s).arg(_valueOf(x)).toLatin1().constData())
35 #define db1 qDebug("Mark Nr. 1")
36 #define db2 qDebug("Mark Nr. 2")
37 #define db3 qDebug("Mark Nr. 3")
38 #define db4 qDebug("Mark Nr. 4")
39 #define dbStart dbs("Starting timer..."); QTime _t; _t.start()
40 #define dbRestart dbp("Elapsed time is %1 ms", _t.restart())
42 // some syntactic sugar
43 #define FOREACH(type, i, c) for (type::const_iterator i((c).constBegin()), \
44 _e##i##_((c).constEnd()); i != _e##i##_; ++i)
46 #define FOREACH_SL(i, c) FOREACH(QStringList, i, c)
48 class QDataStream;
49 class QProcess;
50 class QSplitter;
51 class QWidget;
52 class ShaString;
54 // type shortcuts
55 typedef const QString& SCRef;
56 typedef QStringList& SList;
57 typedef const QStringList& SCList;
58 typedef QVector<QString> StrVect;
59 typedef QVector<ShaString> ShaVect;
60 typedef QSet<QString> ShaSet;
62 uint qHash(const ShaString&); // optimized custom hash for sha strings
64 namespace QGit {
66 // minimum git version required
67 extern const QString GIT_VERSION;
69 // key bindings
70 enum KeyType {
71 KEY_UP,
72 KEY_DOWN,
73 SHIFT_KEY_UP,
74 SHIFT_KEY_DOWN,
75 KEY_LEFT,
76 KEY_RIGHT,
77 CTRL_PLUS,
78 CTRL_MINUS,
79 KEY_U,
80 KEY_D,
81 KEY_DELETE,
82 KEY_B,
83 KEY_BCKSPC,
84 KEY_SPACE,
85 KEY_R,
86 KEY_P,
87 KEY_F
90 // tab pages
91 enum TabType {
92 TAB_REV,
93 TAB_PATCH,
94 TAB_FILE
97 // graph elements
98 enum LaneType {
99 EMPTY,
100 ACTIVE,
101 NOT_ACTIVE,
102 MERGE_FORK,
103 MERGE_FORK_R,
104 MERGE_FORK_L,
105 JOIN,
106 JOIN_R,
107 JOIN_L,
108 HEAD,
109 HEAD_R,
110 HEAD_L,
111 TAIL,
112 TAIL_R,
113 TAIL_L,
114 CROSS,
115 CROSS_EMPTY,
116 INITIAL,
117 BRANCH,
118 UNAPPLIED,
119 APPLIED,
120 BOUNDARY,
121 BOUNDARY_C, // corresponds to MERGE_FORK
122 BOUNDARY_R, // corresponds to MERGE_FORK_R
123 BOUNDARY_L, // corresponds to MERGE_FORK_L
125 LANE_TYPES_NUM
127 const int COLORS_NUM = 8;
129 // graph helpers
130 inline bool isHead(int x) { return (x == HEAD || x == HEAD_R || x == HEAD_L); }
131 inline bool isTail(int x) { return (x == TAIL || x == TAIL_R || x == TAIL_L); }
132 inline bool isJoin(int x) { return (x == JOIN || x == JOIN_R || x == JOIN_L); }
133 inline bool isFreeLane(int x) { return (x == NOT_ACTIVE || x == CROSS || isJoin(x)); }
134 inline bool isBoundary(int x) { return (x == BOUNDARY || x == BOUNDARY_C ||
135 x == BOUNDARY_R || x == BOUNDARY_L); }
136 inline bool isMerge(int x) { return (x == MERGE_FORK || x == MERGE_FORK_R ||
137 x == MERGE_FORK_L || isBoundary(x)); }
138 inline bool isActive(int x) { return (x == ACTIVE || x == INITIAL || x == BRANCH ||
139 isMerge(x)); }
141 // custom events
142 enum EventType {
143 ERROR_EV = 65432,
144 POPUP_LIST_EV = 65433,
145 POPUP_FILE_EV = 65434,
146 POPUP_TREE_EV = 65435,
147 MSG_EV = 65436,
148 ANN_PRG_EV = 65437,
149 UPD_DM_EV = 65438,
150 UPD_DM_MST_EV = 65439
153 // list views columns
154 enum ColumnType {
155 GRAPH_COL = 0,
156 ANN_ID_COL = 1,
157 LOG_COL = 2,
158 AUTH_COL = 3,
159 TIME_COL = 4,
160 COMMIT_COL = 97, // dummy col used for sha searching
161 LOG_MSG_COL = 98, // dummy col used for log messages searching
162 SHA_MAP_COL = 99 // dummy col used when filter output is a set of matching sha
165 inline bool isInfoCol(int x) { return (x == TIME_COL || x == LOG_COL || x == AUTH_COL); }
167 // default list view widths
168 const int DEF_GRAPH_COL_WIDTH = 80;
169 const int DEF_LOG_COL_WIDTH = 500;
170 const int DEF_AUTH_COL_WIDTH = 230;
171 const int DEF_TIME_COL_WIDTH = 160;
173 // colors
174 extern const QColor BROWN;
175 extern const QColor ORANGE;
176 extern const QColor DARK_ORANGE;
177 extern const QColor LIGHT_ORANGE;
178 extern const QColor LIGHT_BLUE;
179 extern const QColor PURPLE;
180 extern const QColor DARK_GREEN;
182 // initialized at startup according to system wide settings
183 extern QColor ODD_LINE_COL;
184 extern QColor EVEN_LINE_COL;
185 extern QFont STD_FONT;
186 extern QFont TYPE_WRITER_FONT;
187 extern QString GIT_DIR;
189 // patches drag and drop
190 extern const QString PATCHES_DIR;
191 extern const QString PATCHES_NAME;
193 // git index parameters
194 extern const QByteArray ZERO_SHA_BA;
195 extern const ShaString ZERO_SHA_RAW;
197 extern const QString ZERO_SHA;
198 extern const QString CUSTOM_SHA;
199 extern const QString ALL_MERGE_FILES;
201 // settings keys
202 extern const QString ORG_KEY;
203 extern const QString APP_KEY;
204 extern const QString GIT_DIR_KEY;
205 extern const QString PATCH_DIR_KEY;
206 extern const QString FMT_P_OPT_KEY;
207 extern const QString AM_P_OPT_KEY;
208 extern const QString STD_FNT_KEY;
209 extern const QString TYPWRT_FNT_KEY;
210 extern const QString FLAGS_KEY;
211 extern const QString CON_GEOM_KEY;
212 extern const QString CMT_GEOM_KEY;
213 extern const QString MAIN_GEOM_KEY;
214 extern const QString REV_GEOM_KEY;
215 extern const QString CMT_TEMPL_KEY;
216 extern const QString CMT_ARGS_KEY;
217 extern const QString RANGE_FROM_KEY;
218 extern const QString RANGE_TO_KEY;
219 extern const QString RANGE_OPT_KEY;
220 extern const QString EX_KEY;
221 extern const QString EX_PER_DIR_KEY;
222 extern const QString EXT_DIFF_KEY;
223 extern const QString REC_REP_KEY;
224 extern const QString ACT_LIST_KEY;
225 extern const QString ACT_GEOM_KEY;
226 extern const QString ACT_GROUP_KEY;
227 extern const QString ACT_TEXT_KEY;
228 extern const QString ACT_FLAGS_KEY;
230 // settings default values
231 extern const QString CMT_TEMPL_DEF;
232 extern const QString EX_DEF;
233 extern const QString EX_PER_DIR_DEF;
234 extern const QString EXT_DIFF_DEF;
236 // settings booleans
237 enum FlagType {
238 MSG_ON_NEW_F = 1 << 0,
239 ACT_REFRESH_F = 1 << 1,
240 NUMBERS_F = 1 << 2,
241 LOG_DIFF_TAB_F = 1 << 3,
242 ACT_CMD_LINE_F = 1 << 4,
243 DIFF_INDEX_F = 1 << 5,
244 SIGN_PATCH_F = 1 << 6,
245 SIGN_CMT_F = 1 << 7,
246 VERIFY_CMT_F = 1 << 8,
247 SMART_LBL_F = 1 << 9,
248 REL_DATE_F = 1 << 10,
249 ALL_BRANCHES_F = 1 << 11,
250 WHOLE_HISTORY_F = 1 << 12,
251 RANGE_SELECT_F = 1 << 13,
252 REOPEN_REPO_F = 1 << 14,
253 USE_CMT_MSG_F = 1 << 15
255 const int FLAGS_DEF = USE_CMT_MSG_F | RANGE_SELECT_F | SMART_LBL_F | VERIFY_CMT_F | SIGN_PATCH_F | LOG_DIFF_TAB_F | MSG_ON_NEW_F;
257 // ShaString helpers
258 const ShaString toTempSha(const QString&); // use as argument only, see definition
259 const ShaString toPersistentSha(const QString&, QVector<QByteArray>&);
261 // settings helpers
262 uint flags(SCRef flagsVariable);
263 bool testFlag(uint f, SCRef fv = FLAGS_KEY);
264 void setFlag(uint f, bool b, SCRef fv = FLAGS_KEY);
266 // tree view icons helpers
267 void initMimePix();
268 void freeMimePix();
269 const QPixmap* mimePix(SCRef fileName);
271 // geometry settings helers
272 typedef QVector<QSplitter*> splitVect;
273 void saveGeometrySetting(SCRef name, QWidget* w = NULL, splitVect* svPtr = NULL);
274 void restoreGeometrySetting(SCRef name, QWidget* w = NULL, splitVect* svPtr = NULL);
276 // misc helpers
277 bool stripPartialParaghraps(const QByteArray& src, QString* dst, QString* prev);
278 bool writeToFile(SCRef fileName, SCRef data, bool setExecutable = false);
279 bool writeToFile(SCRef fileName, const QByteArray& data, bool setExecutable = false);
280 bool readFromFile(SCRef fileName, QString& data);
281 bool startProcess(QProcess* proc, SCList args, SCRef buf = "", bool* winShell = NULL);
283 // cache file
284 const uint C_MAGIC = 0xA0B0C0D0;
285 const int C_VERSION = 15;
287 extern const QString BAK_EXT;
288 extern const QString C_DAT_FILE;
290 // misc
291 const int MAX_DICT_SIZE = 100003; // must be a prime number see QDict docs
292 const int MAX_MENU_ENTRIES = 20;
293 const int MAX_RECENT_REPOS = 7;
294 extern const QString QUOTE_CHAR;
295 extern const QString SCRIPT_EXT;
298 class ShaString : public QLatin1String {
299 public:
300 inline ShaString() : QLatin1String(NULL) {}
301 inline ShaString(const ShaString& sha) : QLatin1String(sha.latin1()) {}
302 inline explicit ShaString(const char* sha) : QLatin1String(sha) {}
304 inline bool operator!=(const ShaString& o) const { return !operator==(o); }
305 inline bool operator==(const ShaString& o) const {
307 return (latin1() == o.latin1()) || !qstrcmp(latin1(), o.latin1());
311 class Rev {
312 // prevent implicit C++ compiler defaults
313 Rev();
314 Rev(const Rev&);
315 Rev& operator=(const Rev&);
316 public:
317 Rev(const QByteArray& b, uint s, int idx, int* next, bool withDiff)
318 : orderIdx(idx), ba(b), start(s) {
320 indexed = isDiffCache = isApplied = isUnApplied = false;
321 descRefsMaster = ancRefsMaster = descBrnMaster = -1;
322 *next = indexData(true, withDiff);
324 bool isBoundary() const { return (ba.at(shaStart - 1) == '-'); }
325 uint parentsCount() const { return parentsCnt; }
326 const ShaString parent(int idx) const;
327 const QStringList parents() const;
328 const ShaString sha() const { return ShaString(ba.constData() + shaStart); }
329 const QString author() const { setup(); return mid(autStart, autDateStart - autStart - 1); }
330 const QString authorDate() const { setup(); return mid(autDateStart, 10); }
331 const QString shortLog() const { setup(); return mid(sLogStart, sLogLen); }
332 const QString longLog() const { setup(); return mid(lLogStart, lLogLen); }
333 const QString diff() const { setup(); return mid(diffStart, diffLen); }
335 QVector<int> lanes, childs;
336 QVector<int> descRefs; // list of descendant refs index, normally tags
337 QVector<int> ancRefs; // list of ancestor refs index, normally tags
338 QVector<int> descBranches; // list of descendant branches index
339 int descRefsMaster; // in case of many Rev have the same descRefs, ancRefs or
340 int ancRefsMaster; // descBranches these are stored only once in a Rev pointed
341 int descBrnMaster; // by corresponding index xxxMaster
342 int orderIdx;
343 private:
344 inline void setup() const { if (!indexed) indexData(false, false); }
345 int indexData(bool quick, bool withDiff) const;
346 const QString mid(int start, int len) const;
347 const QString midSha(int start, int len) const;
349 const QByteArray& ba; // reference here!
350 const int start;
351 mutable int parentsCnt, shaStart, autStart, autDateStart;
352 mutable int sLogStart, sLogLen, lLogStart, lLogLen, diffStart, diffLen;
353 mutable bool indexed;
354 public:
355 bool isDiffCache, isApplied, isUnApplied; // put here to optimize padding
357 typedef QHash<ShaString, const Rev*> RevMap; // faster then a map
360 class RevFile {
362 friend class Cache; // to directly load status
363 friend class Git;
365 // Status information is splitted in a flags vector and in a string
366 // vector in 'status' are stored flags according to the info returned
367 // by 'git diff-tree' without -C option.
368 // In case of a working dir file an IN_INDEX flag is or-ed togheter in
369 // case file is present in git index.
370 // If file is renamed or copied an entry in 'extStatus' stores the
371 // value returned by 'git diff-tree -C' plus source and destination
372 // files info.
373 // When status of all the files is 'modified' then onlyModified is
374 // set, this let us to do some optimization in this common case
375 bool onlyModified;
376 QVector<int> status;
377 QVector<QString> extStatus;
379 // prevent implicit C++ compiler defaults
380 RevFile(const RevFile&);
381 RevFile& operator=(const RevFile&);
382 public:
384 enum StatusFlag {
385 MODIFIED = 1,
386 DELETED = 2,
387 NEW = 4,
388 RENAMED = 8,
389 COPIED = 16,
390 UNKNOWN = 32,
391 IN_INDEX = 64,
392 ANY = 127
395 RevFile() : onlyModified(true) {}
397 /* This QByteArray keeps indices in some dir and names vectors,
398 * defined outside RevFile. Paths are splitted in dir and file
399 * name, first all the dirs are listed then the file names to
400 * achieve a better compression when saved to disk.
401 * A single QByteArray is used instead of two vectors because it's
402 * much faster to load from disk when using a QDataStream
404 QByteArray pathsIdx;
406 int dirAt(uint idx) const { return ((int*)pathsIdx.constData())[idx]; }
407 int nameAt(uint idx) const { return ((int*)pathsIdx.constData())[count() + idx]; }
409 QVector<int> mergeParent;
411 // helper functions
412 int count() const {
414 return pathsIdx.size() / ((int)sizeof(int) * 2);
416 bool statusCmp(int idx, StatusFlag sf) const {
418 return ((onlyModified ? MODIFIED : status.at(idx)) & sf);
420 const QString extendedStatus(int idx) const {
422 rf.extStatus has size equal to position of latest copied/renamed file,
423 that could be lower then count(), so we have to explicitly check for
424 an out of bound condition.
426 return (!extStatus.isEmpty() && idx < extStatus.count() ? extStatus.at(idx) : "");
428 const RevFile& operator>>(QDataStream&) const;
429 RevFile& operator<<(QDataStream&);
431 typedef QHash<ShaString, const RevFile*> RevFileMap;
434 class FileAnnotation {
435 public:
436 explicit FileAnnotation(int id) : isValid(false), annId(id) {}
437 FileAnnotation() : isValid(false) {}
438 QStringList lines;
439 bool isValid;
440 int annId;
441 QString fileSha;
443 typedef QHash<ShaString, FileAnnotation> AnnotateHistory;
446 class BaseEvent: public QEvent {
447 public:
448 BaseEvent(SCRef d, int id) : QEvent((QEvent::Type)id), payLoad(d) {}
449 const QString myData() const { return payLoad; }
450 private:
451 const QString payLoad; // passed by copy
454 #define DEF_EVENT(X, T) class X : public BaseEvent { public: \
455 explicit X (SCRef d) : BaseEvent(d, T) {} }
457 DEF_EVENT(MessageEvent, QGit::MSG_EV);
458 DEF_EVENT(AnnotateProgressEvent, QGit::ANN_PRG_EV);
460 class DeferredPopupEvent : public BaseEvent {
461 public:
462 DeferredPopupEvent(SCRef msg, int type) : BaseEvent(msg, type) {}
465 class MainExecErrorEvent : public BaseEvent {
466 public:
467 MainExecErrorEvent(SCRef c, SCRef e) : BaseEvent("", QGit::ERROR_EV), cmd(c), err(e) {}
468 const QString command() const { return cmd; }
469 const QString report() const { return err; }
470 private:
471 const QString cmd, err;
474 #endif