Logo Search packages:      
Sourcecode: qgit version File versions  Download package

domain.cpp

/*
      Author: Marco Costalba (C) 2005-2006

      Copyright: See COPYING file that comes with this distribution

*/
#include <qapplication.h>
#include <qlistview.h>
#include "git.h"
#include "mainimpl.h"
#include "domain.h"

using namespace QGit;

void StateInfo::S::clear() {

      sha = fn = dtSha = "";
      isM = allM = false;
      sel = true;
}

StateInfo::S& StateInfo::S::operator=(const StateInfo::S& st) {

      if (&st != this) {
            sha   = st.sha;
            fn    = st.fn;
            dtSha = st.dtSha;
            sel   = st.sel;
            isM   = st.isM;
            allM  = st.allM;
      }
      return *this;
}

bool StateInfo::S::operator==(const StateInfo::S& st) const {

      if (&st == this)
            return true;

      return (   sha   == st.sha
              && fn    == st.fn
              && dtSha == st.dtSha
              && sel   == st.sel
              && isM   == st.isM
              && allM  == st.allM );
}

bool StateInfo::S::operator!=(const StateInfo::S& st) const {

      return !(StateInfo::S::operator==(st));
}

void StateInfo::clear() {

      nextS.clear();
      curS.clear();
      prevS.clear();
      isLocked = false;
}

StateInfo& StateInfo::operator=(const StateInfo& newState) {

      if (&newState != this) {
            if (isLocked)
                  nextS = newState.curS;
            else
                  curS = newState.curS; // prevS is mot modified to allow a rollback
      }
      return *this;
}

bool StateInfo::operator==(const StateInfo& newState) const {

      if (&newState == this)
            return true;

      return (curS == newState.curS); // compare is made on curS only
}

bool StateInfo::operator!=(const StateInfo& newState) const {

      return !(StateInfo::operator==(newState));
}

// ************************* Domain ****************************

Domain::Domain(MainImpl* m, Git* g) : QObject(m), git(g) {

      st.clear();
      busy = readyToDrag = dragging = dropping = linked = false;
      popupType = 0;
      tabPosition = -1;

      connect(m, SIGNAL(tabClosed(int)), this, SLOT(on_tabClosed(int)));
}

void Domain::on_closeAllTabs() {

      delete this; // must be sync, deleteLater() does not work
}

void Domain::on_tabClosed(int tabPos) {

      if (tabPosition > tabPos)
            tabPosition--;
}

MainImpl* Domain::m() const { return static_cast<MainImpl*>(parent()); }

bool Domain::setReadyToDrag(bool b) {

      readyToDrag = (b && !busy && !dragging && !dropping);
      return readyToDrag;
}

bool Domain::setDragging(bool b) {

      bool dragFinished = (!b && dragging);

      dragging = (b && readyToDrag && !dropping);

      if (dragging)
            readyToDrag = false;

      if (dragFinished)
            flushQueue();

      return dragging;
}

void Domain::unlinkDomain(Domain* d) {

      d->linked = false;
      while (d->disconnect(SIGNAL(updateRequested(StateInfo)), this))
            ;// a signal is emitted for every connection you make,
             // so if you duplicate a connection, two signals will be emitted.
}

void Domain::linkDomain(Domain* d) {

      unlinkDomain(d); // be sure only one connection is active
      connect(d, SIGNAL(updateRequested(StateInfo)), this, SLOT(on_updateRequested(StateInfo)));
      d->linked = true;
}

void Domain::on_updateRequested(StateInfo newSt) {

      st = newSt;
      UPDATE();
}

bool Domain::flushQueue() {
// during dragging any state update is queued, so try to flush pending now

      if (!busy && st.flushQueue()) {
            UPDATE();
            return true;
      }
      return false;
}

void Domain::customEvent(QCustomEvent* e) {

      bool fromMaster = false;

      switch (e->type()) {
      case UPD_DM_MST_EV:
            fromMaster = true;
            // fall through
      case UPD_DM_EV:
            update(fromMaster);
            break;
      case MSG_EV:
            if (!busy && !st.requestPending())
                  QApplication::postEvent(m(), new MessageEvent(((MessageEvent*)e)->data()));
            else // waiting for the end of updating
                  statusBarRequest = ((MessageEvent*)e)->data();
            break;
      default:
            break;
      }
      QObject::customEvent(e);
}

void Domain::populateState() {

      const Rev* r = git->revLookup(st.sha());
      if (r)
            st.setIsMerge(r->parentsCount() > 1);
}

void Domain::update(bool fromMaster) {

      if (st.sha().isEmpty()) {
            dbs("ASSERT update called with empty sha");
            return;
      }
      if (busy || dragging)
            return;

      if (linked && !fromMaster) {
            // in this case let the update to fall down from master domain
            StateInfo tmp(st);
            st.rollBack(); // we don't want to filter out next update sent from master
            emit updateRequested(tmp);
            return;
      }
      busy = true;

      setReadyToDrag(false); // do not start any drag while updating
      populateState(); // complete any missing state information

      st.setLock(true); // any state change will be queued now

      if (doUpdate())
            st.commit();
      else
            st.rollBack();

      st.setLock(false);

      busy = false;

      bool nextRequestPending = flushQueue();

      if (!nextRequestPending && !statusBarRequest.isEmpty()) {
            // update status bar when we are sure no more work is pending
            QApplication::postEvent(m(), new MessageEvent(statusBarRequest));
            statusBarRequest = "";
      }
      if (!nextRequestPending && popupType)
            sendPopupEvent();
}

void Domain::sendPopupEvent() {

      // call an async context popup, must be executed
      // after returning to event loop
      DeferredPopupEvent* e = new DeferredPopupEvent(popupData, popupType);
      QApplication::postEvent(m(), e);
      popupType = 0;
}

void Domain::on_contextMenu(const QString& data, int type) {

      popupType = type;
      popupData = data;

      if (busy)
            return; // we are in the middle of an update

      // if list view is already updated pop-up
      // context menu, otherwise it means update()
      // has still not been called, a pop-up request,
      // will be fired up at the end of next update()
      if ((type == POPUP_LIST_EV) && (data != st.sha()))
            return;

      sendPopupEvent();
}

Generated by  Doxygen 1.6.0   Back to index