2 Author: Marco Costalba (C) 2005-2007
4 Copyright: See COPYING file that comes with this distribution
14 #include <QLatin1String>
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
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
); }
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)
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
68 // minimum git version required
69 extern const QString GIT_VERSION
;
102 BOUNDARY_C
, // corresponds to MERGE_FORK
103 BOUNDARY_R
, // corresponds to MERGE_FORK_R
104 BOUNDARY_L
, // corresponds to MERGE_FORK_L
108 const int COLORS_NUM
= 8;
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
||
125 POPUP_LIST_EV
= 65433,
126 POPUP_FILE_EV
= 65434,
127 POPUP_TREE_EV
= 65435,
131 UPD_DM_MST_EV
= 65439
134 // list views columns
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;
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
;
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
;
221 MSG_ON_NEW_F
= 1 << 0,
222 ACT_REFRESH_F
= 1 << 1,
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,
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
;
242 const ShaString
toTempSha(const QString
&); // use as argument only, see definition
243 const ShaString
toPersistentSha(const QString
&, QVector
<QByteArray
>&);
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
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
);
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
);
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
;
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
{
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());
296 // prevent implicit C++ compiler defaults
299 Rev
& operator=(const Rev
&);
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
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!
336 mutable int parentsCnt
, shaStart
, comStart
, autStart
, autDateStart
;
337 mutable int sLogStart
, sLogLen
, lLogStart
, lLogLen
, diffStart
, diffLen
;
338 mutable bool indexed
;
340 bool isDiffCache
, isApplied
, isUnApplied
; // put here to optimize padding
342 typedef QHash
<ShaString
, const Rev
*> RevMap
; // faster then a map
347 friend class Cache
; // to directly load status
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
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
362 QVector
<QString
> extStatus
;
364 // prevent implicit C++ compiler defaults
365 RevFile(const RevFile
&);
366 RevFile
& operator=(const RevFile
&);
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
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
;
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
{
421 explicit FileAnnotation(int id
) : isValid(false), annId(id
) {}
422 FileAnnotation() : isValid(false) {}
428 typedef QHash
<ShaString
, FileAnnotation
> AnnotateHistory
;
431 class BaseEvent
: public QEvent
{
433 BaseEvent(SCRef d
, int id
) : QEvent((QEvent::Type
)id
), payLoad(d
) {}
434 const QString
myData() const { return payLoad
; }
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
{
447 DeferredPopupEvent(SCRef msg
, int type
) : BaseEvent(msg
, type
) {}
450 class MainExecErrorEvent
: public BaseEvent
{
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
; }
456 const QString cmd
, err
;
461 QString
qt4and5escaping(QString toescape
);