00001
00002
00003
00004
00005
00006
00007 #include <qapplication.h>
00008 #include <qlistview.h>
00009 #include "exceptionmanager.h"
00010 #include "mainimpl.h"
00011 #include "git.h"
00012 #include "domain.h"
00013
00014 using namespace QGit;
00015
00016 void StateInfo::S::clear() {
00017
00018 sha = fn = dtSha = "";
00019 isM = allM = false;
00020 sel = true;
00021 }
00022
00023 bool StateInfo::S::operator==(const StateInfo::S& st) const {
00024
00025 if (&st == this)
00026 return true;
00027
00028 return ( sha == st.sha
00029 && fn == st.fn
00030 && dtSha == st.dtSha
00031 && sel == st.sel
00032 && isM == st.isM
00033 && allM == st.allM);
00034 }
00035
00036 bool StateInfo::S::operator!=(const StateInfo::S& st) const {
00037
00038 return !(StateInfo::S::operator==(st));
00039 }
00040
00041 void StateInfo::clear() {
00042
00043 nextS.clear();
00044 curS.clear();
00045 prevS.clear();
00046 isLocked = false;
00047 }
00048
00049 StateInfo& StateInfo::operator=(const StateInfo& newState) {
00050
00051 if (&newState != this) {
00052 if (isLocked)
00053 nextS = newState.curS;
00054 else
00055 curS = newState.curS;
00056 }
00057 return *this;
00058 }
00059
00060 bool StateInfo::operator==(const StateInfo& newState) const {
00061
00062 if (&newState == this)
00063 return true;
00064
00065 return (curS == newState.curS);
00066 }
00067
00068 bool StateInfo::operator!=(const StateInfo& newState) const {
00069
00070 return !(StateInfo::operator==(newState));
00071 }
00072
00073 bool StateInfo::isChanged(uint what) const {
00074
00075 bool ret = false;
00076 if (what & SHA)
00077 ret = (sha(true) != sha(false));
00078
00079 if (!ret && (what & FILE_NAME))
00080 ret = (fileName(true) != fileName(false));
00081
00082 if (!ret && (what & DIFF_TO_SHA))
00083 ret = (diffToSha(true) != diffToSha(false));
00084
00085 if (!ret && (what & ALL_MERGE_FILES))
00086 ret = (allMergeFiles(true) != allMergeFiles(false));
00087
00088 return ret;
00089 }
00090
00091
00092
00093 Domain::Domain(MainImpl* m, Git* g) : QObject(m), git(g) {
00094
00095 EM_INIT(exDeleteRequest, "Deleting domain");
00096 EM_INIT(exCancelRequest, "Canceling update");
00097
00098 st.clear();
00099 busy = readyToDrag = dragging = dropping = linked = false;
00100 popupType = 0;
00101 tabPosition = -1;
00102
00103 connect(m, SIGNAL(tabClosed(int)), this, SLOT(on_tabClosed(int)));
00104 }
00105
00106 void Domain::on_closeAllTabs() {
00107
00108 delete this;
00109 }
00110
00111 void Domain::deleteWhenDone() {
00112
00113 if (!EM_IS_PENDING(exDeleteRequest))
00114 EM_RAISE(exDeleteRequest);
00115
00116 emit cancelDomainProcesses();
00117
00118 on_deleteWhenDone();
00119 }
00120
00121 void Domain::on_deleteWhenDone() {
00122
00123 if (!EM_IS_PENDING(exDeleteRequest))
00124 deleteLater();
00125 else
00126 QTimer::singleShot(20, this, SLOT(on_deleteWhenDone()));
00127 }
00128
00129 void Domain::on_tabClosed(int tabPos) {
00130
00131 if (tabPosition > tabPos)
00132 tabPosition--;
00133 }
00134
00135 void Domain::setThrowOnDelete(bool b) {
00136
00137 if (b)
00138 EM_REGISTER(exDeleteRequest);
00139 else
00140 EM_REMOVE(exDeleteRequest);
00141 }
00142
00143 bool Domain::isThrowOnDeleteRaised(int excpId, SCRef curContext) {
00144
00145 return EM_MATCH(excpId, exDeleteRequest, curContext);
00146 }
00147
00148 MainImpl* Domain::m() const {
00149
00150 return static_cast<MainImpl*>(parent());
00151 }
00152
00153 const QString Domain::dragHostName() const {
00154
00155 return QString::fromLatin1("@") + m()->curWorkDir();
00156 }
00157
00158 bool Domain::setReadyToDrag(bool b) {
00159
00160 readyToDrag = (b && !busy && !dragging && !dropping);
00161 return readyToDrag;
00162 }
00163
00164 bool Domain::setDragging(bool b) {
00165
00166 bool dragFinished = (!b && dragging);
00167
00168 dragging = (b && readyToDrag && !dropping);
00169
00170 if (dragging)
00171 readyToDrag = false;
00172
00173 if (dragFinished)
00174 flushQueue();
00175
00176 return dragging;
00177 }
00178
00179 void Domain::unlinkDomain(Domain* d) {
00180
00181 d->linked = false;
00182 while (d->disconnect(SIGNAL(updateRequested(StateInfo)), this))
00183 ;
00184
00185 }
00186
00187 void Domain::linkDomain(Domain* d) {
00188
00189 unlinkDomain(d);
00190 connect(d, SIGNAL(updateRequested(StateInfo)), this, SLOT(on_updateRequested(StateInfo)));
00191 d->linked = true;
00192 }
00193
00194 void Domain::on_updateRequested(StateInfo newSt) {
00195
00196 st = newSt;
00197 UPDATE();
00198 }
00199
00200 bool Domain::flushQueue() {
00201
00202
00203 if (!busy && st.flushQueue()) {
00204 UPDATE();
00205 return true;
00206 }
00207 return false;
00208 }
00209
00210 void Domain::customEvent(QCustomEvent* e) {
00211
00212 bool fromMaster = false;
00213
00214 switch (e->type()) {
00215 case UPD_DM_MST_EV:
00216 fromMaster = true;
00217
00218 case UPD_DM_EV:
00219 update(fromMaster, ((UpdateDomainEvent*)e)->isForced());
00220 break;
00221 case MSG_EV:
00222 if (!busy && !st.requestPending())
00223 QApplication::postEvent(m(), new MessageEvent(((MessageEvent*)e)->myData()));
00224 else
00225 statusBarRequest = ((MessageEvent*)e)->myData();
00226 break;
00227 default:
00228 break;
00229 }
00230 QObject::customEvent(e);
00231 }
00232
00233 void Domain::populateState() {
00234
00235 const Rev* r = git->revLookup(st.sha());
00236 if (r)
00237 st.setIsMerge(r->parentsCount() > 1);
00238 }
00239
00240 void Domain::update(bool fromMaster, bool force) {
00241
00242 if (busy && st.requestPending()) {
00243
00244
00245
00246 EM_RAISE(exCancelRequest);
00247 emit cancelDomainProcesses();
00248 }
00249 if (busy || dragging)
00250 return;
00251
00252 if (linked && !fromMaster) {
00253
00254 StateInfo tmp(st);
00255 st.rollBack();
00256 emit updateRequested(tmp);
00257 return;
00258 }
00259 try {
00260 EM_REGISTER_Q(exCancelRequest);
00261 setThrowOnDelete(true);
00262 git->setThrowOnStop(true);
00263 git->setCurContext(this);
00264 busy = true;
00265 setReadyToDrag(false);
00266 populateState();
00267 st.setLock(true);
00268
00269 if (doUpdate(force))
00270 st.commit();
00271 else
00272 st.rollBack();
00273
00274 st.setLock(false);
00275 busy = false;
00276 if (git->curContext() != this)
00277 qDebug("ASSERT in Domain::update, context is %p "
00278 "instead of %p", (void*)git->curContext(), (void*)this);
00279
00280 git->setCurContext(NULL);
00281 git->setThrowOnStop(false);
00282 setThrowOnDelete(false);
00283 EM_REMOVE(exCancelRequest);
00284
00285 } catch (int i) {
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 st.commit();
00299 st.setLock(false);
00300 busy = false;
00301 git->setCurContext(NULL);
00302 git->setThrowOnStop(false);
00303 setThrowOnDelete(false);
00304 EM_REMOVE(exCancelRequest);
00305
00306 if (QApplication::overrideCursor())
00307 QApplication::restoreOverrideCursor();
00308
00309 QString context("updating ");
00310 if (git->isThrowOnStopRaised(i, context + className())) {
00311 EM_THROW_PENDING;
00312 return;
00313 }
00314 if (isThrowOnDeleteRaised(i, context + className())) {
00315 EM_THROW_PENDING;
00316 return;
00317 }
00318 if (i == exCancelRequest)
00319 EM_THROW_PENDING;
00320
00321 else {
00322 const QString info("Exception \'" + EM_DESC(i) + "\' "
00323 "not handled in init...re-throw");
00324 dbs(info);
00325 throw;
00326 }
00327 }
00328 bool nextRequestPending = flushQueue();
00329
00330 if (!nextRequestPending && !statusBarRequest.isEmpty()) {
00331
00332 QApplication::postEvent(m(), new MessageEvent(statusBarRequest));
00333 statusBarRequest = "";
00334 }
00335 if (!nextRequestPending && popupType)
00336 sendPopupEvent();
00337 }
00338
00339 void Domain::sendPopupEvent() {
00340
00341
00342
00343 DeferredPopupEvent* e = new DeferredPopupEvent(popupData, popupType);
00344 QApplication::postEvent(m(), e);
00345 popupType = 0;
00346 }
00347
00348 void Domain::on_contextMenu(const QString& data, int type) {
00349
00350 popupType = type;
00351 popupData = data;
00352
00353 if (busy)
00354 return;
00355
00356
00357
00358
00359
00360 if ((type == POPUP_LIST_EV) && (data != st.sha()))
00361 return;
00362
00363 sendPopupEvent();
00364 }