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