diff --git a/CMakeLists.txt b/CMakeLists.txt index fbed2818..e7e99317 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ ENABLE_TESTING() SET(UTILS_APP_NAME MacGitver) RAD_DEFINE_VERSION(MACGITVER_CORE 0 0 1) +RAD_DEFINE_VERSION(REPOMAN 0 0 1) ADD_SUBDIRECTORY(CfgComp) diff --git a/Libs/CMakeLists.txt b/Libs/CMakeLists.txt index 26912da6..215a80c8 100644 --- a/Libs/CMakeLists.txt +++ b/Libs/CMakeLists.txt @@ -11,5 +11,8 @@ INCLUDE_DIRECTORIES( BEFORE ) ADD_SUBDIRECTORY(libLogger) +ADD_SUBDIRECTORY(libActivities) ADD_SUBDIRECTORY(libDiffViews) +ADD_SUBDIRECTORY(libRepoMan) ADD_SUBDIRECTORY(libMacGitverCore) + diff --git a/Libs/libActivities/Activity.cpp b/Libs/libActivities/Activity.cpp new file mode 100644 index 00000000..13e3d818 --- /dev/null +++ b/Libs/libActivities/Activity.cpp @@ -0,0 +1,259 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libActivities/Activity.hpp" +#include "libActivities/ActivityPrivate.hpp" +#include "libActivities/StepPrivate.hpp" +#include "libActivities/ManagerPrivate.hpp" + +namespace Activities +{ + + namespace + { + void countTypes(const std::vector& steps, int& pending, int& running, + int& success, int& error) + { + for (auto step : steps) { + switch (step->mState) { + case State::Unknown: + case State::PartiallyFinishedWithErrors: + break; + + case State::Pending: + pending++; + break; + + case State::InProgress: + running++; + break; + + case State::Finished: + success++; + break; + + case State::FinishedWithErrors: + error++; + break; + } + } + } + + State activityState(const std::vector& steps) + { + int pending = 0, running = 0, success = 0, error = 0, total = steps.size(); + countTypes(steps, pending, running, success, error); + + if (total == 0 || pending == total) { + return State::Pending; + } + + if (success == total) { + return State::Finished; + } + + if (error == total) { + return State::FinishedWithErrors; + } + + if (error > 0) { + return State::PartiallyFinishedWithErrors; + } + + Q_ASSERT(running + success > 0); + return State::InProgress; + } + } + + ActivityData::ActivityData(const QString &display) + : mGeneration(ManagerData::nextGeneration()) + , mState(State::Pending) + , mIsDefunct(false) + , mDisplay(display) + , mCurProgress(0) + , mMaxProgress(0) + , mTotalCurProgress(0) + , mTotalMaxProgress(0) + { + } + + ActivityData::~ActivityData() + { + } + + quint32 ActivityData::generation() const + { + return mGeneration; + } + + ActivityData::Ptr ActivityData::getptr() + { + return shared_from_this(); + } + + std::unique_lock ActivityData::uniqueLock() const + { + return std::unique_lock(mMtx); + } + + bool ActivityData::isDefunct() const + { + std::lock_guard _(mMtx); + return mIsDefunct; + } + + void ActivityData::updated(const StepData::Ptr& step, std::unique_lock& lock) + { + mTotalCurProgress = mCurProgress; + mTotalMaxProgress = mMaxProgress; + + for (StepData::Ptr step : mSteps) { + + } + } + + void ActivityData::stepStarted(const StepData::Ptr& step, std::unique_lock &lock) + { + State newState = activityState(mSteps); + } + + void ActivityData::stepFinished(const StepData::Ptr& step, bool failed, std::unique_lock &lock) + { + State newState = activityState(mSteps); + } + + void ActivityData::logUpdated(const LogData::Ptr &log, std::unique_lock &lock) + { + + } + + bool ActivityData::isModalityRequired() const + { + return mForceModalDialog; + } + + // ----- + + Step::Vector Activity::steps() const + { + Step::Vector r; + if (d) { + std::lock_guard _(d->mMtx); + for (const StepData::Ptr& step : d->mSteps) { + r.push_back(step); + } + } + return r; + } + + bool Activity::isDefunct() const + { + if (d) { + return d->isDefunct(); + } + + return true; + } + + Log Activity::log() const + { + if (d) { + std::lock_guard _(d->mMtx); + return {d->mLog}; + } + return {}; + } + + State Activity::state() const + { + if (d) { + std::lock_guard _(d->mMtx); + return d->mState; + } + + return State::Unknown; + } + + QString Activity::display() const + { + if (d) { + std::lock_guard _(d->mMtx); + return d->mDisplay; + } + + return {}; + } + + int Activity::curProgress() const + { + if (d) { + std::lock_guard _(d->mMtx); + return d->mTotalCurProgress; + } + + return 0; + } + + int Activity::maxProgress() const + { + if (d) { + std::lock_guard _(d->mMtx); + return d->mTotalMaxProgress; + } + + return 0; + } + + int Activity::curOwnProgress() const + { + if (d) { + std::lock_guard _(d->mMtx); + return d->mCurProgress; + } + + return 0; + } + + int Activity::maxOwnProgress() const + { + if (d) { + std::lock_guard _(d->mMtx); + return d->mMaxProgress; + } + + return 0; + } + + Step Activity::createStep(const QString& displayName) + { + if (d) { + std::lock_guard _(d->mMtx); + + StepData::Ptr sd = StepData::create(d->getptr(), displayName); + d->mSteps.push_back(sd); + + ManagerData::instance()->enqueue(EventTypes::StepAdded, d->getptr(), sd); + + return {sd}; + } + + return {}; + } + +} diff --git a/Libs/libActivities/Activity.hpp b/Libs/libActivities/Activity.hpp new file mode 100644 index 00000000..c3dbd68c --- /dev/null +++ b/Libs/libActivities/Activity.hpp @@ -0,0 +1,68 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libActivities/Step.hpp" +#include "libActivities/Log.hpp" + +namespace Activities +{ + + class ActivityData; + + class ACTIVITIES_API Activity + { + public: + using Vector = std::vector; + + public: + Activity() = default; + ~Activity() = default; + Activity(const Activity& o) : Activity(o.d) {} + Activity(Activity&& o) : Activity(std::move(o.d)) {} + Activity(const std::shared_ptr& o) : d(o) {} + Activity(std::shared_ptr&& o) : d(std::move(o)) {} + + public: + Step::Vector steps() const; + Step createStep(const QString& displayName); + + public: + State state() const; + QString display() const; + int curProgress() const; + int maxProgress() const; + int curOwnProgress() const; + int maxOwnProgress() const; + Log log() const; + + public: + void setState(State newState); + void setDisplay(const QString& display); + void setProgress(int cur, int max); + + public: + bool isDefunct() const; + + private: + std::shared_ptr d; + }; + +} diff --git a/Libs/libActivities/ActivityPrivate.hpp b/Libs/libActivities/ActivityPrivate.hpp new file mode 100644 index 00000000..bc856168 --- /dev/null +++ b/Libs/libActivities/ActivityPrivate.hpp @@ -0,0 +1,69 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libActivities/StepPrivate.hpp" +#include "libActivities/LogPrivate.hpp" + +namespace Activities +{ + + class ActivityData + : public std::enable_shared_from_this + { + public: + using Steps = std::vector; + using Ptr = std::shared_ptr; + using Vector = std::vector; + + public: + ActivityData(const QString& display); + ~ActivityData(); + + public: + quint32 generation() const; + Ptr getptr(); + std::unique_lock uniqueLock() const; + + void updated(const StepData::Ptr& step, std::unique_lock &lock); + void stepStarted(const StepData::Ptr& step, std::unique_lock &lock); + void stepFinished(const StepData::Ptr& step, bool failed, std::unique_lock &lock); + void logUpdated(const LogData::Ptr& log, std::unique_lock& lock); + + public: + bool isModalityRequired() const; + bool isDefunct() const; + + public: + mutable std::mutex mMtx; + quint32 mGeneration; + State mState; + bool mIsDefunct; + Steps mSteps; + LogData::Ptr mLog; + QString mDisplay; + int mCurProgress; + int mMaxProgress; + int mTotalCurProgress; + int mTotalMaxProgress; + bool mForceModalDialog; + }; + +} diff --git a/Libs/libMacGitverCore/RepoMan/Branch.hpp b/Libs/libActivities/Api.hpp similarity index 59% rename from Libs/libMacGitverCore/RepoMan/Branch.hpp rename to Libs/libActivities/Api.hpp index f511f537..b1f583ba 100644 --- a/Libs/libMacGitverCore/RepoMan/Branch.hpp +++ b/Libs/libActivities/Api.hpp @@ -19,28 +19,10 @@ #pragma once -#include "Ref.hpp" +#include -namespace RM -{ - - class MGV_CORE_API Branch : public Ref - { - public: - enum { StaticObjectType = BranchObject }; - typedef QVector< Branch* > List; - typedef QSet< Branch* > Set; - - public: - Branch(Base* parent, const Git::Reference& ref); - - public: - bool hasUpstream() const; - QString upstreamRefName() const; - Ref* upstream(); - int aheadCount() const; - int behindCount() const; - bool isHead() const; - }; - -} +#ifdef Activities_EXPORTS +# define ACTIVITIES_API Q_DECL_EXPORT +#else +# define ACTIVITIES_API Q_DECL_IMPORT +#endif diff --git a/Libs/libActivities/CMakeLists.txt b/Libs/libActivities/CMakeLists.txt new file mode 100644 index 00000000..2d64923c --- /dev/null +++ b/Libs/libActivities/CMakeLists.txt @@ -0,0 +1,58 @@ + +PROJECT(ACTIVITIES) + +QT_PREPARE(Core) + +SET( SRC_FILES + + Manager.cpp + Activity.cpp + Step.cpp + Log.cpp +) + +SET( PUB_HDR_FILES + + Api.hpp + Manager.hpp + Activity.hpp + Step.hpp + Log.hpp +) + +SET( PRI_HDR_FILES + ManagerPrivate.hpp + ActivityPrivate.hpp + StepPrivate.hpp + LogPrivate.hpp +) + +SET( HDR_FILES ${PRI_HDR_FILES} ${PUB_HDR_FILES} ) + +QT_MOC( MOC_FILES ${HDR_FILES} ) + +ADD_QT_LIBRARY( + Activities SHARED + + ${SRC_FILES} + ${HDR_FILES} + ${MOC_FILES} +) + +TARGET_LINK_LIBRARIES( + Activities +) + +IF(UNIX AND NOT APPLE) + SET_TARGET_PROPERTIES( + Activities + PROPERTIES INSTALL_RPATH + "\$ORIGIN" + ) +ENDIF() + +RAD_DEFINE_VERSION(ACTIVITIES 0 0 1) +RAD_SET_TARGET_VERSION(Activities ACTIVITIES) +RAD_INSTALL_LIBRARY (Activities Activities) +RAD_INSTALL_HEADERS (libActivities ${PUB_HDR_FILES}) +RAD_SPLIT_SOURCE_TREE (libActivities) diff --git a/Libs/libActivities/Log.cpp b/Libs/libActivities/Log.cpp new file mode 100644 index 00000000..813ba221 --- /dev/null +++ b/Libs/libActivities/Log.cpp @@ -0,0 +1,140 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libActivities/LogPrivate.hpp" +#include "libActivities/ActivityPrivate.hpp" + +namespace Activities +{ + + LogData::LogData() + { + } + + LogData::~LogData() + { + } + + LogData::Ptr LogData::getptr() + { + return shared_from_this(); + } + + LogData::Ptr LogData::create() + { + return std::make_shared(); + } + + void LogData::setActivity(ActivityData* activity) + { + mActivity = activity->getptr(); + } + + void LogData::flush() + { + if (mRecoverableLine.isEmpty()) { + return; + } + + mLines << mRecoverableLine; + mRecoverableLine = QString(); + } + + // ---- + + void Log::setRecoverable(const QString& text, bool flush) + { + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + if (flush) { + d->flush(); + } + d->mRecoverableLine = text; + + if (a) { + a->logUpdated(d->getptr(), lock); + } + } + } + + void Log::addLine(const QString& text, bool flush) + { + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + if (flush) { + d->flush(); + } + + d->mLines << text; + + if (a) { + a->logUpdated(d->getptr(), lock); + } + } + } + + QStringList Log::lines() const + { + QStringList sl; + + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + sl = d->mLines; + + if (d->mRecoverableLine.isEmpty()) { + // we definitely want to detach here, since we don't want to return a pointer into + // the mutex-protected string list. + sl.detach(); + } + else { + sl << d->mRecoverableLine; + } + } + + return sl; + } + + bool Log::isDefunct() const + { + if (d) { + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + return a->isDefunct(); + } + } + + return true; + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/Head.hpp b/Libs/libActivities/Log.hpp similarity index 56% rename from Libs/libMacGitverCore/RepoMan/Head.hpp rename to Libs/libActivities/Log.hpp index 5e26d838..44023198 100644 --- a/Libs/libMacGitverCore/RepoMan/Head.hpp +++ b/Libs/libActivities/Log.hpp @@ -19,37 +19,37 @@ #pragma once -#include "RepoMan/Base.hpp" -#include "RepoMan/CollectionNode.hpp" -#include "RepoMan/Branch.hpp" +#include "libActivities/Step.hpp" -namespace RM +#include + +namespace Activities { - namespace Internal - { - class HeadPrivate; - } + class LogData; - class MGV_CORE_API Head : public Base + class ACTIVITIES_API Log { public: - enum { StaticObjectType = HeadObject }; - typedef Internal::HeadPrivate Private; - typedef QSet< Head* > Set; - typedef QVector< Head* > List; + Log() = default; + ~Log() = default; + Log(const Log& o) : Log(o.d) {} + Log(Log&& o) : Log(std::move(o.d)) {} + Log(const std::shared_ptr& o) : d(o) {} + Log(std::shared_ptr&& o) : d(std::move(o)) {} public: - Head(const Git::Repository& repo, Base* parent); + void setRecoverable(const QString& text, bool flush = false); + void addLine(const QString& text, bool flush = true); public: - bool isDetached() const; - bool isUnborn() const; - Git::ObjectId detachedId() const; - QString symbolicName() const; + QStringList lines() const; public: - bool is(const Branch* ref) const; + bool isDefunct() const; + + private: + std::shared_ptr d; }; } diff --git a/Libs/libMacGitverCore/RepoMan/Namespace.hpp b/Libs/libActivities/LogPrivate.hpp similarity index 58% rename from Libs/libMacGitverCore/RepoMan/Namespace.hpp rename to Libs/libActivities/LogPrivate.hpp index 2a0d986e..e1ab6eaf 100644 --- a/Libs/libMacGitverCore/RepoMan/Namespace.hpp +++ b/Libs/libActivities/LogPrivate.hpp @@ -19,36 +19,43 @@ #pragma once -#include "Base.hpp" -#include "CollectionNode.hpp" +#include "libActivities/Log.hpp" -namespace RM +#include + +#include + +namespace Activities { - namespace Internal - { - class NamespacePrivate; - } + class ActivityData; - class MGV_CORE_API Namespace : public Base + class LogData + : public std::enable_shared_from_this { public: - enum { StaticObjectType = NamespaceObject }; - typedef Internal::NamespacePrivate Private; - typedef QSet< Namespace* > Set; - typedef QVector< Namespace* > List; + using Ptr = std::shared_ptr; + + public: + LogData(); + ~LogData(); + + public: + static Ptr create(); + + public: + Ptr getptr(); public: - Namespace(Base* parent, const QString& _name); + void setActivity(ActivityData* activity); public: - QString name() const; + void flush(); public: - CollectionNode* branches(); - CollectionNode* namespaces(); - CollectionNode* notes(); - CollectionNode* tags(); + std::weak_ptr mActivity; + QString mRecoverableLine; + QStringList mLines; }; } diff --git a/Libs/libActivities/Manager.cpp b/Libs/libActivities/Manager.cpp new file mode 100644 index 00000000..28898d45 --- /dev/null +++ b/Libs/libActivities/Manager.cpp @@ -0,0 +1,356 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libActivities/ManagerPrivate.hpp" + +#include +#include +#include + +namespace Activities +{ + + constexpr int ALLOWED_EMPTY_TIMERS = 8; // 8 * 750ms = 6 seconds before we stop "timing" + constexpr int TIMER_INTERVAL = 750; + constexpr int SHOW_DIALOG_AFTER = 5000; + constexpr int HIDE_DIALOG_AFTER = 30000; + + bool EventInfo::operator==(const EventInfo& o) const + { + if (type != o.type) { + return false; + } + + switch (type) { + case EventTypes::StepAdded: + case EventTypes::StepRemoved: + case EventTypes::StepUpdated: + if (step != o.step) { + return false; + } + // fall through + case EventTypes::LogUpdated: + case EventTypes::ActivityAdded: + case EventTypes::ActivityRemoved: + case EventTypes::ActivityUpdated: + if (activity != o.activity) { + return false; + } + // fall through + case EventTypes::GlobalState: + break; + } + + return true; + } + + std::unique_lock ManagerData::getLock() + { + static std::mutex sMutex; + return std::unique_lock(sMutex); + } + + ManagerData::ManagerData() + : mOwner(nullptr) + , mUpdateTimer(nullptr) + , mAllowedEmptyTimers(ALLOWED_EMPTY_TIMERS) + { + if (QThread::currentThread() != qApp->thread()) { + // However we got created, force ourselves into the main thread... + moveToThread(qApp->thread()); + } + + setParent(qApp); + + qRegisterMetaType(); + } + + ManagerData::~ManagerData() + { + std::unique_lock l(getLock()); + sSelf = nullptr; + } + + ManagerData* ManagerData::sSelf = nullptr; + + quint32 ManagerData::nextGeneration() + { + static quint32 ng = 0; + return ++ng; + } + + ManagerData* ManagerData::instance() + { + if (!sSelf) { + std::unique_lock l(getLock()); + if (!sSelf) { + sSelf = new ManagerData; + } + } + + return sSelf; + } + + Activity ManagerData::newActivity(const QString& display) + { + std::unique_lock lock(ManagerData::getLock()); + ActivityData::Ptr ad { std::make_shared(display) }; + + mCurActivities.push_back(ad); + + lock.unlock(); + enqueue(EventTypes::ActivityAdded, ad); + + return {ad}; + } + + void ManagerData::enqueue(EventInfo&& ei) + { + std::unique_lock lock { getLock() }; + + for (const EventInfo& temp : mEvents) { + if (temp == ei) { + return; + } + } + + mEvents.push_back(std::move(ei)); + + if (maybeStartEventSending() || ei.type == EventTypes::GlobalState) { + updateGlobalState(); + } + } + + bool ManagerData::maybeStartEventSending() + { + if (mUpdateTimer && mUpdateTimer->isActive()) { + return false; + } + + if (!mUpdateTimer) { + mUpdateTimer = new QTimer; + + if (QThread::currentThread() != thread()) { // Likely + mUpdateTimer->moveToThread(thread()); + } + + mUpdateTimer->setParent(this); + + qDebug() << "Created update timer"; + + connect(mUpdateTimer, &QTimer::timeout, this, &ManagerData::sendEvents); + } + + mAllowedEmptyTimers = ALLOWED_EMPTY_TIMERS; + mUpdateTimer->start(TIMER_INTERVAL); + + qDebug() << "Started the update timer"; + + return true; + } + + void ManagerData::sendEvents() + { + EventInfo::Vector events; + + if (QThread::currentThread() != qApp->thread()) { + // This should actually not happen, since the timer ought to deliver events to the + // right thread in the first place. + qDebug() << "Activities::ManagerData::sendEvents() was called in non-gui-thread!"; + QMetaObject::invokeMethod(this, "sendEvents", Qt::QueuedConnection); + return; + } + + { + // We're keeping the mutex lock as small as possible, so we don't bother the worker + // thread to wait for us to send out events... + std::unique_lock lock { getLock() }; + events.swap(mEvents); + + if (events.empty()) { + if (!--mAllowedEmptyTimers) { + qDebug() << "No events for " << ALLOWED_EMPTY_TIMERS * TIMER_INTERVAL << "ms. " + "Stopping the update timer."; + mUpdateTimer->stop(); + } + return; + } + else { + mAllowedEmptyTimers = ALLOWED_EMPTY_TIMERS; + } + } + + + std::sort(events.begin(), events.end(), [](const EventInfo& a, const EventInfo& b) -> bool { + + if (a.type < b.type) { + return true; + } + + if (b.type < a.type) { + return false; + } + + Q_ASSERT(a.activity && b.activity); + + if (a.activity->generation() < b.activity->generation()) { + return true; + } + if (b.activity->generation() < a.activity->generation()) { + return false; + } + + if (a.type == EventTypes::StepAdded || + a.type == EventTypes::StepRemoved || + a.type == EventTypes::StepUpdated) { + + Q_ASSERT(a.step && b.step); + + if (a.step->generation() < b.step->generation()) { + return true; + } + if (b.step->generation() < a.step->generation()) { + return false; + } + } + + // If we're still here, then we're the same type and neither one of the activity nor + // step generation number is either less or greater -> We're equal! But we want to be + // unique, so equality is impossible... + Q_ASSERT(false); + Q_UNREACHABLE(); + }); + + for (EventInfo& ei : events) { + switch (ei.type) { + case EventTypes::ActivityAdded: + mOwner->activityCreated({ei.activity}); + break; + + case EventTypes::ActivityRemoved: + mOwner->activityRemoved({ei.activity}); + break; + + case EventTypes::ActivityUpdated: + mOwner->activityUpdated({ei.activity}); + break; + + case EventTypes::LogUpdated: + mOwner->logUpdated({ei.activity}); + break; + + case EventTypes::StepAdded: + mOwner->stepCreated({ei.activity}, {ei.step}); + break; + + case EventTypes::StepRemoved: + mOwner->stepRemoved({ei.activity}, {ei.step}); + break; + + case EventTypes::StepUpdated: + mOwner->stepUpdated({ei.activity}, {ei.step}); + break; + + case EventTypes::GlobalState: + { + std::unique_lock lock(getLock()); + mOwner->updateGlobalActivity(mCurrentGlobalState); + } + break; + } + } + } + + bool ManagerData::isModalityRequired() const + { + bool required = false; + + for (const ActivityData::Ptr& a : mCurActivities) { + if (a->isModalityRequired()) { + required = true; + break; + } + } + + return required; + } + + void ManagerData::updateGlobalState() + { + + } + + // ----- + + Manager::Manager() + { + if (QThread::currentThread() != qApp->thread()) { + // However we got created, force ourselves into the main thread... + moveToThread(qApp->thread()); + } + + setParent(qApp); + } + + Manager& Manager::instance() + { + ManagerData* d = ManagerData::instance(); + Q_ASSERT(d); + if (!d->mOwner) { + d->mOwner = new Manager; + } + return *d->mOwner; + } + + Activity Manager::createActivity(const QString& display) + { + ManagerData* d = ManagerData::instance(); + return d->newActivity(display); + } + + Activity::Vector Manager::activities() const + { + ManagerData* d = ManagerData::instance(); + std::unique_lock lock(ManagerData::getLock()); + + Activity::Vector result; + for (auto a : d->mCurActivities) { + result.push_back({a}); + } + + return result; + } + + void Manager::requestProgressDialog() + { + bool requireModal; + + { + std::unique_lock lock(ManagerData::getLock()); + ManagerData* d = ManagerData::instance(); + + // this ought to be false, if this method is used correctly. But timing could interfere + // here. + requireModal = d->isModalityRequired(); + } + + emit showProgressDialog(requireModal); + } + +} diff --git a/Libs/libActivities/Manager.hpp b/Libs/libActivities/Manager.hpp new file mode 100644 index 00000000..3bd1576c --- /dev/null +++ b/Libs/libActivities/Manager.hpp @@ -0,0 +1,79 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libActivities/Activity.hpp" + +#include + +namespace Activities +{ + + struct GlobalSnapShot + { + int mNumActivities; + int mRunningActivities; + int mDoneActivities; + int mFailedActivities; + + int mCurProgress; + int mMaxProgress; + + QString mUpfrontName; // The name of the first registered activity. This is really + // arbitrary as we obviously cannot display all of them in + // the global snap shot. + }; + + class ACTIVITIES_API Manager + : public QObject + { + Q_OBJECT + private: + Manager(); + public: + ~Manager() = default; + + static Manager& instance(); + + public: + Activity createActivity(const QString& display); + + public: + void requestProgressDialog(); + Activity::Vector activities() const; + + signals: + void activityCreated(Activities::Activity); + void activityUpdated(Activities::Activity); + void activityRemoved(Activities::Activity); + void stepCreated(Activities::Activity, Activities::Step); + void stepUpdated(Activities::Activity, Activities::Step); + void stepRemoved(Activities::Activity, Activities::Step); + void logUpdated(Activities::Activity); + + signals: + void updateGlobalActivity(Activities::GlobalSnapShot); + void showProgressDialog(bool modal); + void hideProgressDialog(); + }; + +} + +Q_DECLARE_METATYPE(Activities::GlobalSnapShot) diff --git a/Libs/libActivities/ManagerPrivate.hpp b/Libs/libActivities/ManagerPrivate.hpp new file mode 100644 index 00000000..355164b8 --- /dev/null +++ b/Libs/libActivities/ManagerPrivate.hpp @@ -0,0 +1,140 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libActivities/Manager.hpp" +#include "libActivities/ActivityPrivate.hpp" + +class QTimer; + +namespace Activities +{ + + enum class EventTypes + { + ActivityAdded, + ActivityUpdated, + ActivityRemoved, + + StepAdded, + StepUpdated, + StepRemoved, + + LogUpdated, + + GlobalState + }; + + #if defined(__cpp_constexpr) && (__cpp_constexpr >= 201304L) + constexpr + #else + static inline + #endif + int eventGroup(EventTypes et) + { + switch (et) { + case EventTypes::ActivityAdded: return 1; + case EventTypes::StepAdded: return 2; + case EventTypes::ActivityUpdated: return 3; + case EventTypes::StepUpdated: return 4; + case EventTypes::LogUpdated: return 5; + case EventTypes::StepRemoved: return 6; + case EventTypes::ActivityRemoved: return 7; + case EventTypes::GlobalState: return 8; + } + } + + #if defined(__cpp_constexpr) && (__cpp_constexpr >= 201304L) + constexpr + #else + static inline + #endif + bool operator<(EventTypes a, EventTypes b) + { + int l1 = eventGroup(a), l2 = eventGroup(b); + return l1 < l2; + } + + struct EventInfo + { + using Vector = std::vector; + + EventTypes type; + ActivityData::Ptr activity; + StepData::Ptr step; + + bool operator==(const EventInfo& o) const; + EventInfo(EventTypes t, ActivityData::Ptr a, StepData::Ptr s = {}) + : type(t), activity(a), step(s) + {} + }; + + class Manager; + + class ManagerData + : public QObject + { + Q_OBJECT + private: + ManagerData(); + public: + ~ManagerData(); + + public: + static ManagerData* instance(); + static std::unique_lock getLock(); + static quint32 nextGeneration(); + + public: + bool isModalityRequired() const; + Activity newActivity(const QString &display); + + public: + void enqueue(EventInfo&& ei); + + template + void enqueue(T&& ... t) + { + // Since we can't bind a brace-initialised object to an xvalue, this method can be used + // instead, like: enqueue(EventType::Foo, bar); + EventInfo ei(std::forward(t)...); + enqueue(std::move(ei)); + } + + private slots: + void sendEvents(); + + private: + bool maybeStartEventSending(); + void updateGlobalState(); + + public: + Manager* mOwner; + ActivityData::Vector mCurActivities; + QTimer* mUpdateTimer; + int mAllowedEmptyTimers; + EventInfo::Vector mEvents; + GlobalSnapShot mCurrentGlobalState; + + private: + static ManagerData* sSelf; + }; + +} diff --git a/Libs/libActivities/Step.cpp b/Libs/libActivities/Step.cpp new file mode 100644 index 00000000..37986eed --- /dev/null +++ b/Libs/libActivities/Step.cpp @@ -0,0 +1,263 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libActivities/StepPrivate.hpp" +#include "libActivities/ActivityPrivate.hpp" +#include "libActivities/ManagerPrivate.hpp" + +namespace Activities +{ + + StepData::StepData(const ActivityData::Ptr& activity, const QString& display) + : mActivity(activity) + , mGeneration(ManagerData::nextGeneration()) + , mState(State::Pending) + , mDisplayName(display) + , mCurProgress(0) + , mMaxProgress(0) + { + } + + StepData::~StepData() + { + } + + StepData::Ptr StepData::getptr() + { + return shared_from_this(); + } + + quint32 StepData::generation() const + { + return mGeneration; + } + + StepData::Ptr StepData::create(const ActivityData::Ptr& activity, const QString& display) + { + return std::make_shared(activity, display); + } + + void StepData::changeState(State newState, std::unique_lock& lock) + { + ActivityData::Ptr a; + + if (mState == newState) { + return; + } + + if (newState == State::PartiallyFinishedWithErrors || + newState == State::Unknown) { + qDebug() << "Invalid new state" << newState << "for Activities::Step"; + return; + } + + switch (mState) { + case State::Unknown: + case State::PartiallyFinishedWithErrors: + qDebug() << "Invalid current state" << newState << "for Activities::Step"; + return; + + case State::Pending: + if (newState == State::InProgress) { + mState = newState; + if ((a = mActivity.lock())) { + a->stepStarted(getptr(), lock); + } + } + // Fall through + + case State::InProgress: + if (newState == State::Finished || newState == State::FinishedWithErrors) { + mState = newState; + if ((a = mActivity.lock())) { + a->stepFinished(getptr(), newState == State::FinishedWithErrors, lock); + } + } + break; + + case State::Finished: + case State::FinishedWithErrors: + // No change allowed + qDebug() << "Invalid Activities::Step state transition:" + << mState << "to" << newState; + + newState = mState; + break; + } + } + + State Step::state() const + { + State s { State::Unknown }; + + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + s = d->mState; + } + + return s; + } + + QString Step::displayName() const + { + QString r; + + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + r = d->mDisplayName; + } + return r; + } + + QString Step::statusText() const + { + QString r; + + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + r = d->mStatusText; + } + return r; + } + + int Step::curProgress() const + { + int r = 0; + + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + r = d->mCurProgress; + } + return r; + } + + int Step::maxProgress() const + { + int r = 0; + + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + r = d->mMaxProgress; + } + return r; + } + + void Step::setState(State newState) + { + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + d->changeState(newState, lock); + } + } + + void Step::setDisplayName(const QString& name) + { + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + d->mDisplayName = name; + + if (a) { + a->updated(d, lock); + } + } + } + + void Step::setStatusText(const QString& text) + { + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + d->mStatusText = text; + + if (a) { + a->updated(d, lock); + } + } + } + + void Step::setProgress(int cur, int max) + { + if (d) { + std::unique_lock lock; + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + lock = a->uniqueLock(); + } + + d->mCurProgress = cur; + d->mMaxProgress = max; + + if (a) { + a->updated(d, lock); + } + } + } + + bool Step::isDefunct() const + { + if (d) { + ActivityData::Ptr a = d->mActivity.lock(); + if (a) { + return a->isDefunct(); + } + } + + return true; + } + +} diff --git a/Libs/libActivities/Step.hpp b/Libs/libActivities/Step.hpp new file mode 100644 index 00000000..2df90744 --- /dev/null +++ b/Libs/libActivities/Step.hpp @@ -0,0 +1,80 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libActivities/Api.hpp" + +#include +#include + +class QString; + +namespace Activities +{ + + class Activity; + class StepData; + + enum class State + { + Unknown, + + Pending, + InProgress, + Finished, + FinishedWithErrors, + + PartiallyFinishedWithErrors + }; + + class ACTIVITIES_API Step + { + public: + using Vector = std::vector; + + public: + Step() = default; + ~Step() = default; + Step(const Step& o) : Step(o.d) {} + Step(Step&& o) : Step(std::move(o.d)) {} + Step(const std::shared_ptr& o) : d(o) {} + Step(std::shared_ptr&& o) : d(std::move(o)) {} + + public: + State state() const; + QString displayName() const; + QString statusText() const; + int curProgress() const; + int maxProgress() const; + + public: + void setState(State newState); + void setDisplayName(const QString& name); + void setStatusText(const QString& text); + void setProgress(int cur, int max); + + public: + bool isDefunct() const; + + private: + std::shared_ptr d; + }; + +} diff --git a/Libs/libActivities/StepPrivate.hpp b/Libs/libActivities/StepPrivate.hpp new file mode 100644 index 00000000..2f55c2b1 --- /dev/null +++ b/Libs/libActivities/StepPrivate.hpp @@ -0,0 +1,94 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libActivities/Step.hpp" + +#include +#include + +#include + +namespace Activities +{ + + class ActivityData; + + class StepData + : public std::enable_shared_from_this + { + public: + using Ptr = std::shared_ptr; + using Vector = std::vector; + + public: + StepData(const std::shared_ptr& activity, const QString& display); + ~StepData(); + + public: + static Ptr create(const std::shared_ptr& activity, const QString& display); + + public: + quint32 generation() const; + Ptr getptr(); + + public: + QString displayName() const; + QString statusText() const; + int curProgress() const; + int maxProgress() const; + + public: + void changeState(State newState, std::unique_lock &lock); + void setDisplayName(const QString& name); + void setStatusText(const QString& text); + void setProgress(int cur, int max); + + public: + std::weak_ptr mActivity; + quint32 mGeneration; + State mState; + QString mStatusText; + QString mDisplayName; + int mCurProgress; + int mMaxProgress; + }; + +} + +static inline +QDebug operator<<(QDebug dbg, Activities::State state) +{ + switch (state) { + case Activities::State::Unknown: + return dbg << "State::Unknown"; + case Activities::State::Pending: + return dbg << "State::Pending"; + case Activities::State::Finished: + return dbg << "State::Finished"; + case Activities::State::FinishedWithErrors: + return dbg << "State::FinishedWithErrors"; + case Activities::State::InProgress: + return dbg << "State::InProgress"; + case Activities::State::PartiallyFinishedWithErrors: + return dbg << "State::PartiallyFinishedWithErrors"; + } + Q_UNREACHABLE(); +} diff --git a/Libs/libMacGitverCore/App/MacGitver.cpp b/Libs/libMacGitverCore/App/MacGitver.cpp index b8974e17..f282d30b 100644 --- a/Libs/libMacGitverCore/App/MacGitver.cpp +++ b/Libs/libMacGitverCore/App/MacGitver.cpp @@ -32,9 +32,11 @@ #include "libMacGitverCore/App/MgvPrimaryWindow.hpp" #include "libMacGitverCore/Config/Config.h" #include "libMacGitverCore/Config/Ui/GeneralConfigPage.hpp" +#include "libMacGitverCore/Config/Ui/RepoManConfigPage.hpp" #include "libMacGitverCore/MacGitver/Modules.h" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/Config/RepoManConfigPage.hpp" +#include "libMacGitverCore/MacGitver/AutoRefresher.hpp" + +#include "libRepoMan/RepoMan.hpp" /** * @class MacGitver @@ -55,6 +57,7 @@ MacGitverPrivate::MacGitverPrivate(MacGitver* owner, bool runGui) : isGui(runGui) + , refresher(nullptr) { sSelf = owner; } @@ -67,6 +70,9 @@ void MacGitverPrivate::init() QApplication::setOrganizationName(QStringLiteral("MacGitver")); QApplication::setApplicationName(QStringLiteral("MacGitver")); + // only start the auto refresher if we're running a GUI + refresher = new AutoRefresher; + Heaven::IconManager::self().defaultProvider()->addSearchPath(QStringLiteral(":/Images")); } else { QApplication::setOrganizationName(QStringLiteral("MacGitver")); @@ -207,3 +213,8 @@ bool MacGitver::isRunningGui() const { return d->isGui; } + +AutoRefresher* MacGitver::refresher() const +{ + return d->refresher; +} diff --git a/Libs/libMacGitverCore/App/MacGitver.hpp b/Libs/libMacGitverCore/App/MacGitver.hpp index 000e8901..276be1ee 100644 --- a/Libs/libMacGitverCore/App/MacGitver.hpp +++ b/Libs/libMacGitverCore/App/MacGitver.hpp @@ -38,6 +38,7 @@ namespace RM typedef BlueSky::ViewDescriptor::CreatorFunc MgvViewCreator; +class AutoRefresher; class MacGitverPrivate; class MGV_CORE_API MacGitver @@ -67,6 +68,8 @@ class MGV_CORE_API MacGitver MgvViewCreator creator); void unregisterView(const BlueSky::ViewIdentifier& identifier); + AutoRefresher *refresher() const; + static void log(Log::Type type, const QString& logMessage); static void log(Log::Type type, const char* logMessage); static void log(Log::Type type, const Git::Result& r, const char* logMessage = nullptr); diff --git a/Libs/libMacGitverCore/App/MacGitverPrivate.hpp b/Libs/libMacGitverCore/App/MacGitverPrivate.hpp index 3b891404..6516c2e9 100644 --- a/Libs/libMacGitverCore/App/MacGitverPrivate.hpp +++ b/Libs/libMacGitverCore/App/MacGitverPrivate.hpp @@ -27,6 +27,7 @@ class QDir; class Modules; +class AutoRefresher; struct MgvViewInfo { @@ -62,6 +63,7 @@ private slots: Git::GitWrap mGitWrap; bool isGui; MgvApp bsApp; + AutoRefresher* refresher; static MacGitver* sSelf; static Modules* sModules; }; diff --git a/Libs/libMacGitverCore/App/MgvPrimaryWindow.cpp b/Libs/libMacGitverCore/App/MgvPrimaryWindow.cpp index 54b77419..bbba0f90 100644 --- a/Libs/libMacGitverCore/App/MgvPrimaryWindow.cpp +++ b/Libs/libMacGitverCore/App/MgvPrimaryWindow.cpp @@ -22,12 +22,12 @@ #include "libMacGitverCore/App/MgvPrimaryWindowPrivate.hpp" #include "libMacGitverCore/MacGitver/Modules.h" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" - #include "libMacGitverCore/Config/Config.h" #include "libMacGitverCore/Config/Ui/ConfigDialog.hpp" #include "libMacGitverCore/Widgets/RepoStateWidget.hpp" +#include "libRepoMan/RepoMan.hpp" + #include "libBlueSky/Application.hpp" #include "libBlueSky/FooterWidget.hpp" diff --git a/Libs/libMacGitverCore/CMakeLists.txt b/Libs/libMacGitverCore/CMakeLists.txt index b95cfac2..9ed93c6a 100644 --- a/Libs/libMacGitverCore/CMakeLists.txt +++ b/Libs/libMacGitverCore/CMakeLists.txt @@ -20,30 +20,12 @@ SET( SRC_FILES Config/Ui/ConfigPage.cpp Config/Ui/GeneralConfigPage.cpp Config/Ui/ConfigPageProvider.cpp + Config/Ui/RepoManConfigPage.cpp MacGitver/Module.cpp MacGitver/Modules.cpp MacGitver/GitPatchConsumer.cpp - - RepoMan/AutoRefresher.cpp - RepoMan/Base.cpp - RepoMan/Ref.cpp - RepoMan/Branch.cpp - RepoMan/CollectionNode.cpp - RepoMan/Events.cpp - RepoMan/Repo.cpp - RepoMan/RepoMan.cpp - RepoMan/Remote.cpp - RepoMan/Tag.cpp - RepoMan/RefLog.cpp - RepoMan/Submodule.cpp - RepoMan/RefTreeNode.cpp - RepoMan/Namespace.cpp - RepoMan/Head.cpp - - RepoMan/Private/Dumper.cpp - - RepoMan/Config/RepoManConfigPage.cpp + MacGitver/AutoRefresher.cpp SHMParser/ShellExpand.cpp @@ -77,21 +59,6 @@ SET( PUB_HDR_FILES MacGitver/GitPatchConsumer.hpp MacGitver/IRepositoryContext.hpp - RepoMan/Base.hpp - RepoMan/Events.hpp - RepoMan/CollectionNode.hpp - RepoMan/Ref.hpp - RepoMan/Repo.hpp - RepoMan/RepoMan.hpp - RepoMan/Remote.hpp - RepoMan/Tag.hpp - RepoMan/Branch.hpp - RepoMan/RefLog.hpp - RepoMan/Submodule.hpp - RepoMan/RefTreeNode.hpp - RepoMan/Namespace.hpp - RepoMan/Head.hpp - SHMParser/ShellExpand.hpp Widgets/ExpandableDlg.hpp @@ -112,31 +79,17 @@ SET( PRI_HDR_FILES App/MacGitverPrivate.hpp App/MgvPrimaryWindowPrivate.hpp + MacGitver/AutoRefresher.hpp + Config/Ui/ConfigDialog.hpp Config/Ui/GeneralConfigPage.hpp - - RepoMan/AutoRefresher.hpp - - RepoMan/Private/BasePrivate.hpp - RepoMan/Private/BranchPrivate.hpp - RepoMan/Private/CollectionNodePrivate.hpp - RepoMan/Private/NamespacePrivate.hpp - RepoMan/Private/RefPrivate.hpp - RepoMan/Private/RefLogPrivate.hpp - RepoMan/Private/RefTreeNodePrivate.hpp - RepoMan/Private/RemotePrivate.hpp - RepoMan/Private/RepoPrivate.hpp - RepoMan/Private/RepoManPrivate.hpp - RepoMan/Private/SubmodulePrivate.hpp - RepoMan/Private/TagPrivate.hpp - RepoMan/Private/Dumper.hpp - RepoMan/Private/HeadPrivate.hpp - - RepoMan/Config/RepoManConfigPage.hpp + Config/Ui/RepoManConfigPage.hpp Widgets/StringSelectorWidgetPrivate.h Widgets/FlatTreeModelPrivate.h Widgets/RepoStateWidget.hpp + + MacGitver/AutoRefresher.hpp ) SET( UI_FILES @@ -145,8 +98,7 @@ SET( UI_FILES Config/Ui/ConfigDialog.ui Config/Ui/GeneralConfigPage.ui - - RepoMan/Config/RepoManConfigPage.ui + Config/Ui/RepoManConfigPage.ui Widgets/ExpandableDlg.ui ) @@ -154,7 +106,6 @@ SET( UI_FILES SET( HID_FILES App/MgvPrimaryWindowActions.hid - RepoMan/Private/RepoManActions.hid ) @@ -165,7 +116,7 @@ SET(RCC_FILES SET( HDR_FILES ${PRI_HDR_FILES} ${PUB_HDR_FILES} ) SET(CCFG_FILES - RepoMan/AutoRefresherCfg.ccfg + MacGitver/AutoRefresherCfg.ccfg ) CFGCOMP(CFG_FILES ${CCFG_FILES}) @@ -195,6 +146,7 @@ TARGET_LINK_LIBRARIES( HeavenIcons BlueSky Logger + RepoMan LINK_PRIVATE GitWrap diff --git a/Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.cpp b/Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.cpp similarity index 89% rename from Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.cpp rename to Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.cpp index 6a122fcd..e3a82093 100644 --- a/Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.cpp +++ b/Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.cpp @@ -17,18 +17,16 @@ * */ -#include "libMacGitverCore/RepoMan/Config/RepoManConfigPage.hpp" -#include "libMacGitverCore/RepoMan/Private/RepoManPrivate.hpp" -#include "libMacGitverCore/RepoMan/AutoRefresher.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" +#include "libMacGitverCore/Config/Ui/RepoManConfigPage.hpp" +#include "libMacGitverCore/MacGitver/AutoRefresher.hpp" #include "libMacGitverCore/App/MacGitver.hpp" IMPLEMENT_NESTED_PAGE_CREATOR(RepoManConfigPage, 210) RepoManConfigPage::RepoManConfigPage(ConfigDialog* dlg) : ConfigPage(dlg) - , refresher(NULL) + , refresher(MacGitver::self().refresher()) { setupUi(this); @@ -71,10 +69,7 @@ void RepoManConfigPage::apply() void RepoManConfigPage::init() { - RM::RepoMan* rm = &RM::RepoMan::instance(); - - RM::Internal::RepoManPrivate* rmp = RM::Internal::BasePrivate::dataOf(rm); - refresher = rmp->refresher; + Q_ASSERT(refresher); grpEnableAutoRefresh->setChecked(refresher->refreshEnabled()); diff --git a/Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.hpp b/Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.hpp similarity index 94% rename from Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.hpp rename to Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.hpp index 979536bf..c3661d9b 100644 --- a/Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.hpp +++ b/Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.hpp @@ -25,10 +25,7 @@ #include "ui_RepoManConfigPage.h" -namespace RM -{ - class AutoRefresher; -} +class AutoRefresher; class RepoManConfigPage : public ConfigPage @@ -55,5 +52,5 @@ private slots: QWidget* widget(); private: - RM::AutoRefresher* refresher; + AutoRefresher* refresher; }; diff --git a/Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.ui b/Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.ui similarity index 100% rename from Libs/libMacGitverCore/RepoMan/Config/RepoManConfigPage.ui rename to Libs/libMacGitverCore/Config/Ui/RepoManConfigPage.ui diff --git a/Libs/libMacGitverCore/MacGitver/AutoRefresher.cpp b/Libs/libMacGitverCore/MacGitver/AutoRefresher.cpp new file mode 100644 index 00000000..311a4628 --- /dev/null +++ b/Libs/libMacGitverCore/MacGitver/AutoRefresher.cpp @@ -0,0 +1,203 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libMacGitverCore/MacGitver/AutoRefresher.hpp" +#include "AutoRefresherCfg.hpp" + +#include "libRepoMan/RepoMan.hpp" + +#include +#include + +AutoRefresher::AutoRefresher() + : QObject() + , refreshGitTimer(nullptr) + , refreshIndexTimer(nullptr) + , refreshWorktreeTimer(nullptr) +{ + new AutoRefresherCfg(this); + + forcedUpdate(); +} + +AutoRefresher::~AutoRefresher() +{ +} + +bool AutoRefresher::refreshEnabled() const +{ + return AutoRefresherCfg::refreshEnabled(); +} + +bool AutoRefresher::refreshGitEnabled() const +{ + return AutoRefresherCfg::gitInterval() != 0; +} + +bool AutoRefresher::refreshIndexEnabled() const +{ + return AutoRefresherCfg::indexInterval() != 0; +} + +bool AutoRefresher::refreshWorktreeEnabled() const +{ + return AutoRefresherCfg::worktreeInterval() != 0; +} + +void AutoRefresher::setRefreshEnabled(bool enabled) +{ + AutoRefresherCfg::setRefreshEnabled(enabled); + forcedUpdate(); +} + +void AutoRefresher::forcedUpdate() +{ + setRefreshGitInterval(AutoRefresherCfg::gitInterval(), true); + setRefreshIndexInterval(AutoRefresherCfg::indexInterval(), true); + setRefreshWorktreeInterval(AutoRefresherCfg::worktreeInterval(), true); +} + +void AutoRefresher::setRefreshGitInterval(int interval, bool force) +{ + if (interval < 15) { + interval = 0; + } + + if (interval == AutoRefresherCfg::gitInterval() ) { + if (!force) { + return; + } + } + else { + AutoRefresherCfg::setGitInterval(interval); + } + + if (interval) { + if (!refreshGitTimer) { + refreshGitTimer = new QTimer(this); + connect(refreshGitTimer, SIGNAL(timeout()), + this, SLOT(onRefreshGit())); + } + refreshGitTimer->setInterval(interval * 1000); + refreshGitTimer->start(); + } + else { + if (refreshGitTimer) { + refreshGitTimer->stop(); + refreshGitTimer->deleteLater(); + refreshGitTimer = NULL; + } + } +} + +void AutoRefresher::setRefreshIndexInterval(int interval, bool force) +{ + if (interval < 30) { + interval = 0; + } + + if (interval == AutoRefresherCfg::indexInterval() ) { + if (!force) { + return; + } + } + else { + AutoRefresherCfg::setIndexInterval(interval); + } + + if (interval) { + if (!refreshIndexTimer) { + refreshIndexTimer = new QTimer(this); + connect(refreshIndexTimer, SIGNAL(timeout()), + this, SLOT(onRefreshIndex())); + } + refreshIndexTimer->setInterval(interval * 1000); + refreshIndexTimer->start(); + } + else { + if (refreshIndexTimer) { + refreshIndexTimer->stop(); + refreshIndexTimer->deleteLater(); + refreshIndexTimer = NULL; + } + } +} + +void AutoRefresher::setRefreshWorktreeInterval(int interval, bool force) +{ + if (interval < 120) { + interval = 0; + } + + if (interval == AutoRefresherCfg::worktreeInterval() ) { + if (!force) { + return; + } + } + else { + AutoRefresherCfg::setWorktreeInterval(interval); + } + + if (interval) { + if (!refreshWorktreeTimer) { + refreshWorktreeTimer = new QTimer(this); + connect(refreshWorktreeTimer, SIGNAL(timeout()), + this, SLOT(onRefreshWorktree())); + } + refreshWorktreeTimer->setInterval(interval * 1000); + refreshWorktreeTimer->start(); + } + else { + if (refreshWorktreeTimer) { + refreshWorktreeTimer->stop(); + refreshWorktreeTimer->deleteLater(); + refreshWorktreeTimer = NULL; + } + } +} + +int AutoRefresher::gitRefreshInterval() const +{ + return AutoRefresherCfg::gitInterval(); +} + +int AutoRefresher::indexRefreshInterval() const +{ + return AutoRefresherCfg::indexInterval(); +} + +int AutoRefresher::worktreeRefreshInterval() const +{ + return AutoRefresherCfg::worktreeInterval(); +} + +void AutoRefresher::onRefreshGit() +{ + qDebug() << "Refresh Repository currently not implemented."; +} + +void AutoRefresher::onRefreshIndex() +{ + qDebug() << "Refresh Index currently not implemented."; +} + +void AutoRefresher::onRefreshWorktree() +{ + qDebug() << "Refresh Worktree currently not implemented."; +} diff --git a/Libs/libMacGitverCore/MacGitver/AutoRefresher.hpp b/Libs/libMacGitverCore/MacGitver/AutoRefresher.hpp new file mode 100644 index 00000000..c7d42d9c --- /dev/null +++ b/Libs/libMacGitverCore/MacGitver/AutoRefresher.hpp @@ -0,0 +1,63 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include + +class QTimer; + +#include "libMacGitverCore/Config/ConfigUser.h" + +class AutoRefresher + : public QObject +{ + Q_OBJECT +public: + AutoRefresher(); + ~AutoRefresher(); + +public: + bool refreshEnabled() const; + bool refreshGitEnabled() const; + bool refreshIndexEnabled() const; + bool refreshWorktreeEnabled() const; + + int gitRefreshInterval() const; + int indexRefreshInterval() const; + int worktreeRefreshInterval() const; + + void setRefreshEnabled(bool enabled); + void setRefreshGitInterval(int interval, bool force = false); + void setRefreshIndexInterval(int interval, bool force = false); + void setRefreshWorktreeInterval(int interval, bool force = false); + +private slots: + void onRefreshGit(); + void onRefreshIndex(); + void onRefreshWorktree(); + +private: + void forcedUpdate(); + +private: + QTimer* refreshGitTimer; + QTimer* refreshIndexTimer; + QTimer* refreshWorktreeTimer; +}; diff --git a/Libs/libMacGitverCore/RepoMan/AutoRefresherCfg.ccfg b/Libs/libMacGitverCore/MacGitver/AutoRefresherCfg.ccfg similarity index 100% rename from Libs/libMacGitverCore/RepoMan/AutoRefresherCfg.ccfg rename to Libs/libMacGitverCore/MacGitver/AutoRefresherCfg.ccfg diff --git a/Libs/libMacGitverCore/MacGitver/IRepositoryContext.hpp b/Libs/libMacGitverCore/MacGitver/IRepositoryContext.hpp index 3ad14874..ff11181b 100644 --- a/Libs/libMacGitverCore/MacGitver/IRepositoryContext.hpp +++ b/Libs/libMacGitverCore/MacGitver/IRepositoryContext.hpp @@ -23,13 +23,16 @@ namespace RM { - class Repo; + namespace Frontend + { + class Repo; + } } class IRepositoryContext { public: - virtual RM::Repo* repository() const = 0; + virtual RM::Frontend::Repo repository() const = 0; }; Q_DECLARE_INTERFACE( IRepositoryContext, diff --git a/Libs/libMacGitverCore/RepoMan/AutoRefresher.cpp b/Libs/libMacGitverCore/RepoMan/AutoRefresher.cpp deleted file mode 100644 index cb446fff..00000000 --- a/Libs/libMacGitverCore/RepoMan/AutoRefresher.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include - -#include "libMacGitverCore/App/MacGitver.hpp" - -#include "libMacGitverCore/RepoMan/AutoRefresher.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" - -#include "AutoRefresherCfg.hpp" - -namespace RM -{ - - AutoRefresher::AutoRefresher(QObject* parent) - : QObject(parent) - , refreshGitTimer(NULL) - , refreshIndexTimer(NULL) - , refreshWorktreeTimer(NULL) - { - new AutoRefresherCfg(this); - - forcedUpdate(); - } - - AutoRefresher::~AutoRefresher() - { - } - - bool AutoRefresher::refreshEnabled() const - { - return AutoRefresherCfg::refreshEnabled(); - } - - bool AutoRefresher::refreshGitEnabled() const - { - return AutoRefresherCfg::gitInterval() != 0; - } - - bool AutoRefresher::refreshIndexEnabled() const - { - return AutoRefresherCfg::indexInterval() != 0; - } - - bool AutoRefresher::refreshWorktreeEnabled() const - { - return AutoRefresherCfg::worktreeInterval() != 0; - } - - void AutoRefresher::setRefreshEnabled(bool enabled) - { - AutoRefresherCfg::setRefreshEnabled(enabled); - forcedUpdate(); - } - - void AutoRefresher::forcedUpdate() - { - setRefreshGitInterval(AutoRefresherCfg::gitInterval(), true); - setRefreshIndexInterval(AutoRefresherCfg::indexInterval(), true); - setRefreshWorktreeInterval(AutoRefresherCfg::worktreeInterval(), true); - } - - void AutoRefresher::setRefreshGitInterval(int interval, bool force) - { - if (interval < 15) { - interval = 0; - } - - if (interval == AutoRefresherCfg::gitInterval() ) { - if (!force) { - return; - } - } - else { - AutoRefresherCfg::setGitInterval(interval); - } - - if (interval) { - if (!refreshGitTimer) { - refreshGitTimer = new QTimer(this); - connect(refreshGitTimer, SIGNAL(timeout()), - this, SLOT(onRefreshGit())); - } - refreshGitTimer->setInterval(interval * 1000); - refreshGitTimer->start(); - } - else { - if (refreshGitTimer) { - refreshGitTimer->stop(); - refreshGitTimer->deleteLater(); - refreshGitTimer = NULL; - } - } - } - - void AutoRefresher::setRefreshIndexInterval(int interval, bool force) - { - if (interval < 30) { - interval = 0; - } - - if (interval == AutoRefresherCfg::indexInterval() ) { - if (!force) { - return; - } - } - else { - AutoRefresherCfg::setIndexInterval(interval); - } - - if (interval) { - if (!refreshIndexTimer) { - refreshIndexTimer = new QTimer(this); - connect(refreshIndexTimer, SIGNAL(timeout()), - this, SLOT(onRefreshIndex())); - } - refreshIndexTimer->setInterval(interval * 1000); - refreshIndexTimer->start(); - } - else { - if (refreshIndexTimer) { - refreshIndexTimer->stop(); - refreshIndexTimer->deleteLater(); - refreshIndexTimer = NULL; - } - } - } - - void AutoRefresher::setRefreshWorktreeInterval(int interval, bool force) - { - if (interval < 120) { - interval = 0; - } - - if (interval == AutoRefresherCfg::worktreeInterval() ) { - if (!force) { - return; - } - } - else { - AutoRefresherCfg::setWorktreeInterval(interval); - } - - if (interval) { - if (!refreshWorktreeTimer) { - refreshWorktreeTimer = new QTimer(this); - connect(refreshWorktreeTimer, SIGNAL(timeout()), - this, SLOT(onRefreshWorktree())); - } - refreshWorktreeTimer->setInterval(interval * 1000); - refreshWorktreeTimer->start(); - } - else { - if (refreshWorktreeTimer) { - refreshWorktreeTimer->stop(); - refreshWorktreeTimer->deleteLater(); - refreshWorktreeTimer = NULL; - } - } - } - - int AutoRefresher::gitRefreshInterval() const - { - return AutoRefresherCfg::gitInterval(); - } - - int AutoRefresher::indexRefreshInterval() const - { - return AutoRefresherCfg::indexInterval(); - } - - int AutoRefresher::worktreeRefreshInterval() const - { - return AutoRefresherCfg::worktreeInterval(); - } - - void AutoRefresher::onRefreshGit() - { - Log::Manager().addMessage(trUtf8("Refreshing git repositories...")); - RM::RepoMan::instance().refresh(); - } - - void AutoRefresher::onRefreshIndex() - { - } - - void AutoRefresher::onRefreshWorktree() - { - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/AutoRefresher.hpp b/Libs/libMacGitverCore/RepoMan/AutoRefresher.hpp deleted file mode 100644 index 6d3de627..00000000 --- a/Libs/libMacGitverCore/RepoMan/AutoRefresher.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#pragma once - -#include - -class QTimer; - -#include "libMacGitverCore/Config/ConfigUser.h" - -namespace RM -{ - - class AutoRefresher : public QObject - { - Q_OBJECT - public: - AutoRefresher(QObject* parent); - ~AutoRefresher(); - - public: - bool refreshEnabled() const; - bool refreshGitEnabled() const; - bool refreshIndexEnabled() const; - bool refreshWorktreeEnabled() const; - - int gitRefreshInterval() const; - int indexRefreshInterval() const; - int worktreeRefreshInterval() const; - - void setRefreshEnabled(bool enabled); - void setRefreshGitInterval(int interval, bool force = false); - void setRefreshIndexInterval(int interval, bool force = false); - void setRefreshWorktreeInterval(int interval, bool force = false); - - private slots: - void onRefreshGit(); - void onRefreshIndex(); - void onRefreshWorktree(); - - private: - void forcedUpdate(); - - private: - QTimer* refreshGitTimer; - QTimer* refreshIndexTimer; - QTimer* refreshWorktreeTimer; - }; - -} diff --git a/Libs/libMacGitverCore/RepoMan/Base.cpp b/Libs/libMacGitverCore/RepoMan/Base.cpp deleted file mode 100644 index c8d7e53e..00000000 --- a/Libs/libMacGitverCore/RepoMan/Base.cpp +++ /dev/null @@ -1,664 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include -#include - -#include "libHeavenIcons/IconRef.hpp" - -#include "App/MacGitver.hpp" - -#include "Base.hpp" -#include "Repo.hpp" -#include "RepoMan.hpp" -#include "RefTreeNode.hpp" -#include "CollectionNode.hpp" -#include "Events.hpp" - -#include "Private/RepoManPrivate.hpp" -#include "Private/Dumper.hpp" -#include "Private/BasePrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - /** - * @class Base - * @brief Base class for all RepoMan objects - * - * This base class takes care of a unified linking between a parent and its children. Children - * are always created with a pointer to their parent. Children may never be reparented. Only a - * parent is allowed to create children for itself. - * - * Further, the Base class takes care of keeping the strict logic of the refresh process. For - * details on how to implement the refresh logic, see refresh(). - * - * Finally, this base class allows to dump a partial subtree of RepoMan objects into a textual - * hierarchy. See dump() on advanced information. - * - */ - - /** - * @fn bool Base::refreshSelf() - * @brief Refresh this object's data and sent events - * - * This method is called during the refreshing mechanism. It is the first step and can determine - * that the object itself does no longer exist. However, if this happens, the child refreshing - * logic of the parent is most probably broken. - * - * Implementations should _only_ refresh the object itself and not the children. See refresh() - * for details on how exactly the refreshing process works. - */ - - /** - * @fn bool Base::isA() - * @brief Check this object's type - * - * @tparam T Type to check against - * - * @return `true`, if this is an object of type @a T. `false` otherwise. - */ - - /*-* // Keep this comment away from doxygen: https://bugzilla.gnome.org/show_bug.cgi?id=709052 - * @fn T::Set Base::childObjects() const - * @brief Find (existing) children filtered by a given type - * - * @tparam T Type to check the children against - * - * @return A set of children of type @a T. - */ - - /** - * @brief Constructor - * - * Creates a new RepoMan object and links it into the parent. Because at this point the new - * child is not yet fully constructed, no further action is taken. - * - * @param[in] parent The parent to whom we shall link this new child to. - * - */ - Base::Base(BasePrivate& _d) - : mData(&_d) - { - } - - /** - * @brief Destructor - * - * At the point where the destructor is called, all children should have been unlinked from the - * tree and this object has to be unlinked too. - * - */ - Base::~Base() - { - delete mData; - } - - /** - * @brief Find (existing) children - * - * @return A set of all children of this object (unfiltered). - */ - Base::Set Base::childObjects() const - { - RM_CD(Base); - - return d->mChildren; - } - - /** - * @brief Find (existing) children of a specific type - * - * @param[in] type The object type of the children to find. - * - * @return A set of children of this object filtered by object type. - * - */ - Base::Set Base::childObjects(ObjTypes type) const - { - RM_CD(Base); - - Set children; - - foreach(Base* child, d->mChildren) { - if (child->objType() == type) { - children.insert(child); - } - } - - return children; - } - - /** - * @brief Get the direct parent object - * - * The direct parent object is specified during construction and can never be changed. - * - * @return The direct parent object. - * - */ - Base* Base::parentObject() const - { - RM_CD(Base); - - return d->mParentObj->mPub; - } - - /** - * @brief Refresh this object - * - * Refreshs this object and all its children. - * - */ - void Base::refresh() - { - RM_D(Base); - d->refresh(); - } - - /** - * @brief Find the repository for this object - * - * @return The first repository in hierarchy (Repo or Submodule) - * - */ - const Repo* Base::repository() const - { - RM_CD(Base); - return d->mRepo; - } - - /** - * @brief find the repository for this object - * - * Walks up the hierarchy of objects to find the repository. Since objects can never be - * reparented, the result of this method never changes. - * - * @return The first repository in hierarchy that is found - * - */ - Repo* Base::repository() - { - RM_D(Base); - return d->mRepo; - } - - /** - * @brief Get a string that can be used to display this object - * - * @return Always ``. Reimplementations should return something more meaningful. - * - */ - QString Base::displayName() const - { - RM_CD(Base); - return d->displayName(); - } - - /** - * @brief Get the type of this object - * - * This method must be implemented by all derivats of Base. They must simply return the correct - * value from the ObjTypes enum. - * - * @return Type of this object - * - */ - ObjTypes Base::objType() const - { - RM_CD(Base); - return d->objType(); - } - - /** - * @brief Creates a textual dump of this object and its children - * - * @return Textual dump. - * - */ - QString Base::dump() const - { - RM_CD(Base); - - Dumper dumper; - d->dumpRecursive(dumper); - return dumper.output(); - } - - /** - * @brief Get the name of this object type - * - * @return The name - * - */ - QString Base::typeName() const - { - RM_CD(Base); - return d->objectTypeName(); - } - - /** - * @brief Get a context menu for this object - * - * @return A Heaven::Menu that can be used as context menu for this object. - * - */ - Heaven::Menu* Base::contextMenu() - { - RepoMan* rm = &MacGitver::repoMan(); - RepoMan::Private* rmp = BasePrivate::dataOf(rm); - return rmp->contextMenuFor(this); - } - - /** - * @brief Get an icon for this object - * - * @return A iconRef for this object - * - */ - Heaven::IconRef Base::icon(bool small) const - { - RM_D(Base); - return d->icon(small); - } - - bool Base::inheritsRepoManType(ObjTypes type) const - { - RM_CD(Base); - return d->inherits(type); - } - - //-- BasePrivate ---------------------------------------------------------------------------- >8 - - BasePrivate::BasePrivate(Base* pub) - : mPub(pub) - , mRepo(NULL) - , mParentObj(NULL) - { - Q_ASSERT(mPub); - } - - BasePrivate::~BasePrivate() - { - // THIS _IS_ IMPORTANT - // We forbid by definition that any RM::* object may be destroyed _before_ it is unlinked - // from its parent. Otherwise, events cannot be triggered correctly. - Q_ASSERT(mChildren.count() == 0); - Q_ASSERT(mParentObj == NULL); - Q_ASSERT(mRepo == NULL); - } - - /** - * @brief Child-part of linking into the tree - * - * @param[in] parent The parent to link into - * - * This method is called directly from the constructor. It establishes a relationship with the - * parent object. This relationship can never be altered. - * - */ - void BasePrivate::linkToParent(Base* parent) - { - if (parent) { - mParentObj = parent->mData; - mParentObj->addChildObject(mPub); - mRepo = searchRepository(); - refreshSelf(); - postCreation(); - } - } - - /** - * @internal - * @brief Child-Part of unlinking from the tree - * - * Invokes the parent part on the parent side and then cleans up the reference to the parent. - */ - void BasePrivate::unlinkFromParent() - { - if (mParentObj) { - mParentObj->removeChildObject(mPub); - mParentObj = NULL; - mRepo = NULL; - } - } - - /** - * @internal - * @brief Parent-part of linking a new child - * - * We cannot do any special processing, since the child object is not yet fully constructed. We - * just fill the internal structure. - * - * @param[in] object The new child object that shall be linked in. - */ - void BasePrivate::addChildObject(Base* object) - { - Q_ASSERT(object); - Q_ASSERT(!mChildren.contains(object)); - mChildren.insert(object); - } - - /** - * @internal - * @brief Parent-part of unlinking a child from the parent - * - * @param[in] object The child that is to be removed from the parent - */ - void BasePrivate::removeChildObject(Base* object) - { - Q_ASSERT(mChildren.contains(object)); - mChildren.remove(object); - } - - /** - * @internal - * @brief Recursively dump this object into a dumper - * - * All children will be dumped recursively. - * - * @param[in] dumper The dumper to output to - * - */ - void BasePrivate::dumpRecursive(Dumper& dumper) const - { - dumpSelf(dumper); - - dumper.indent(); - foreach(Base* child, mChildren) { - child->mData->dumpRecursive(dumper); - } - dumper.dedent(); - } - - QString BasePrivate::displayName() const - { - return QStringLiteral(""); - } - - /** - * @brief Refresh this object - * - * Refreshes this object and all its children. First calls to refreshSelf() expecting it to - * update this object and send out events. If refreshSelf() returns `false`, this object is - * removed from the tree. In this case all children should already have been removed from the - * tree. - * - * If refreshSelf() returned `true`, preRefreshChildren() is called. It should remove children - * that are no longer part of the tree. After that for each child, refresh() is called - * recursively. Finally, postRefreshChildren() is invoked, which should search for new objects - * and link them into the tree. - * - * If preRefreshChildren() is implemented correctly on all objects, refreshSelf() should - * probably never have to return `false`. - * - */ - void BasePrivate::refresh() - { - if (!refreshSelf()) { - // If refresh self returned false, we are no longer valid and will now destroy - // ourselves. We just terminateObject(). - terminateObject(); - return; - } - - postRefresh(); - preRefreshChildren(); - - foreach(Base* child, mChildren) { - child->mData->refresh(); - } - - postRefreshChildren(); - - if (refreshCheckDispensable()) { - terminateObject(); - } - } - - void BasePrivate::postRefresh() - { - } - - /** - * @brief Check if this object is dispensable - * - * @return @c true to dispense this object - * - * During the refresh cycle, this is the last method called for each object. If it returns - * @c true, the object will be terminated. - * - * This can be used for container objects that shall actually get dispensed once they have no - * more children (i.e. RefTreeNode). - * - */ - bool BasePrivate::refreshCheckDispensable() - { - return false; - } - - /** - * @brief First step in refreshing the children - * - * This method is called directly after the object refreshed itself (refreshSelf()) but before - * any of its children are refreshed. - * - * It shall be used to figure out which children do no longer exist. - * - * The base implementation simply does nothing. - * - */ - void BasePrivate::preRefreshChildren() - { - } - - /** - * @brief Last step in refreshing the children - * - * This method is called as last step in the refreshing process. It shall be used to find - * objects and add them to the tree. - * - * The base implementation simply does nothing. - * - */ - void BasePrivate::postRefreshChildren() - { - } - - /** - * @brief Terminates the lifetime of this object - * - * This method MUST be used to destroy an object. Don't just delete an repoman object. - * - * 1. For all children, terminateObject() gets invoked. - * 2. preTerminate() is called, whose objective is to send an event if required. - * 3. the object is unlinkedFromParent() - * 4. finally it deletes itself. Deleting is not defered; the object is gone immediately. - * - */ - void BasePrivate::terminateObject() - { - foreach (Base* child, mChildren) { - child->mData->terminateObject(); - } - - preTerminate(); - unlinkFromParent(); - delete this; - } - - /** - * @brief Are Events blocked for the repository this object belongs to? - * - * @return `true` if any events for this repository shall be suppressed. `false` in normal - * operation. - * - * During the construction of a repository and its initial seeding with objects, no events will - * be send to any listeners. This method must be used to query whether we're currently in that - * phase or not. - * - */ - bool BasePrivate::repoEventsBlocked() - { - Q_ASSERT(mRepo); - return mRepo->isInitializing(); - } - - /** - * @brief Pre-Termination call - * - * This method is called prior to doing the actual object termination. Its objective is to send - * out any required events to listeners, unless this repository is still initializing. - * - * The base implementation will send out a objectAboutToDelete() event. - */ - void BasePrivate::preTerminate() - { - if (!repoEventsBlocked()) { - Events::self()->objectAboutToBeDeleted(repository(), mPub); - } - } - - /** - * @brief Post-Construction call - * - * This method is called just before the last constructor is finished. The call actually will - * come from linkToParent(). - * - * The purpose of this method is to send a creation event. The base implementation will send a - * objectCreated() event. - * - * Note that no events should be sent out, if repoEventsBlocked() returns `true`. - * - */ - void BasePrivate::postCreation() - { - if (!repoEventsBlocked()) { - Events::self()->objectCreated(repository(), mPub); - } - } - - /** - * @brief Find the parent for a Ref. - * - * @param[in] scopes List of scopes to search for or to create. - * - * @param[in] create If `true` and @a path is not empty, a reference tree node will be - * created, if none is found. If `false`, `NULL` will be returned. - * - * @return If @a scopes is empty, `this` is returned. Otherwise findRefTreeNode() is called - * to either find or create a RefTreeNode, which will be returned. - */ - Base* BasePrivate::findRefParent(const QStringList& scopes, bool create) - { - if (scopes.isEmpty()) { - return mPub; - } - return findRefTreeNode(scopes, create); - } - - /** - * @brief Search for or create a ref tree node - * - * Searches for a RefTreeNode for path. - * - * @param[in] scopes List of scopes to search for or to create. Must not be empty. - * - * @param[in] create If `true` and a part of the tree node cannot be found, it will be - * created. If `false`, `NULL` will be returned in that case. - * - * @return If @a create is `true`, a valid RefTreeNode is returned. If @a create is - * `false`, `NULL` will be returned in case the path cannot be found. - */ - RefTreeNode* BasePrivate::findRefTreeNode(const QStringList &scopes, bool create) - { - if (scopes.isEmpty()) { - return NULL; - } - - Base* current = mPub; - - foreach (QString scope, scopes) { - RefTreeNode::Set nodes = current->childObjects(); - RefTreeNode* next = NULL; - - foreach(RefTreeNode* child, nodes) { - if (child->name() == scope) { - next = child; - break; - } - } - - if (!next) { - if (create) { - // Note: We don't need to roll this back. Either we go all the way or nowhere. - next = new RefTreeNode(current, scope); - } - else { - return NULL; - } - } - - current = next; - } - - return static_cast< RefTreeNode* >(current); - } - - - CollectionNode* BasePrivate::getOrCreateCollection(CollectionTypes ctype) - { - CollectionNode* cn; - - foreach (cn, mPub->childObjects()) { - if (cn->collectionType() == ctype) { - return cn; - } - } - - return new CollectionNode(ctype, mPub); - } - - Repo* BasePrivate::searchRepository() - { - if (!mRepo) { - if (mParentObj) { - mRepo = mParentObj->repository(); - } - else { - return NULL; - } - } - return mRepo; - } - - Heaven::IconRef BasePrivate::icon(bool small) const - { - QString size = small ? QStringLiteral("@16") : QStringLiteral("@24"); - return Heaven::IconRef::fromString(QChar(L'#') % objectTypeName() % size); - } - - bool BasePrivate::inherits(ObjTypes type) const - { - return false; - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/Base.hpp b/Libs/libMacGitverCore/RepoMan/Base.hpp deleted file mode 100644 index 888212b8..00000000 --- a/Libs/libMacGitverCore/RepoMan/Base.hpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#pragma once - -#include -#include -#include - -#include "libMacGitverCore/MacGitverApi.hpp" - -namespace Heaven { - - class Menu; - class IconRef; - -} - -namespace RM -{ - - enum ObjTypes - { - InvalidObject, - - CollectionNodeObject, - NamespaceObject, - RepoManagerObject, - - // repositories - RepoObject, - RemoteObject, - SubmoduleObject, - HeadObject, - - // references - BranchObject, - RefObject, - RefTreeNodeObject, - TagObject, - - RefLogObject - }; - - enum CollectionTypes - { - ctBranches, - ctNamespaces, - ctNotes, - ctTags - }; - - class Repo; - class RefTreeNode; - class CollectionNode; - class Namespace; - class Ref; - class Remote; - class RefLog; - class Submodule; - class Tag; - - namespace Internal - { - class Dumper; - class BasePrivate; - } - - class MGV_CORE_API Base - { - friend class Repo; - friend class Internal::BasePrivate; - - public: - typedef QVector< Base* > List; - typedef QSet< Base* > Set; - - protected: - Base(Internal::BasePrivate& _d); - virtual ~Base(); - - public: - ObjTypes objType() const; - - public: - void refresh(); - - const Repo* repository() const; - Repo* repository(); - - Base* parentObject() const; - - Set childObjects() const; - Set childObjects(ObjTypes type) const; - - template< class T > - typename T::Set childObjects() const; - - template< class T > - bool isA() const; - - template< class T > - bool inheritsRepoManType() const; - - bool inheritsRepoManType(ObjTypes type) const; - - Heaven::IconRef icon(bool small = false) const; - - QString typeName() const; - QString displayName() const; - QString dump() const; - - Heaven::Menu* contextMenu(); - - protected: - Internal::BasePrivate* mData; - - private: - Base(const Base& other); - Base& operator=(const Base& other); - }; - - template< class T > - inline bool Base::isA() const - { - return objType() == ObjTypes(T::StaticObjectType); - } - - template< class T > - inline bool Base::inheritsRepoManType() const - { - return inheritsRepoManType(ObjTypes(T::StaticObjectType)); - } - - template< class T > - inline typename T::Set Base::childObjects() const - { - /* - Set children = childObjects(T::StaticObjType); - typename T::Set typedChildren; - - foreach(Base* child, children) { - typedChildren.insert(static_cast(child)); - } - - return typedChildren; - */ - // Equivalent, but faster: - typename T::Set children; - - foreach(Base* child, childObjects()) { - if (child->inheritsRepoManType()) { - children.insert(static_cast(child)); - } - } - - return children; - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/Branch.cpp b/Libs/libMacGitverCore/RepoMan/Branch.cpp deleted file mode 100644 index dd0115ae..00000000 --- a/Libs/libMacGitverCore/RepoMan/Branch.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include "RepoMan/Branch.hpp" -#include "RepoMan/Repo.hpp" -#include "RepoMan/Events.hpp" -#include "RepoMan/Head.hpp" - -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/BranchPrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - Branch::Branch(Base* parent, const Git::Reference &ref) - : Ref( *new BranchPrivate(this, ref) ) - { - RM_D(Branch); - d->linkToParent( parent ); - } - - QString Branch::upstreamRefName() const - { - RM_CD(Branch); - return d->mUpstreamRefName; - } - - Ref* Branch::upstream() - { - return repository()->findReference(upstreamRefName()); - } - - bool Branch::hasUpstream() const - { - RM_CD(Branch); - return d->mHasUpstream; - } - - int Branch::aheadCount() const - { - RM_CD(Branch); - return d->mAheadCount; - } - - int Branch::behindCount() const - { - RM_CD(Branch); - return d->mBehindCount; - } - - bool Branch::isHead() const - { - const Repo* r = repository(); - const Head* h = r ? r->head() : NULL; - return h && h->is(this); - } - - //-- BranchPrivate ----------------------------------------------------------------------------- - - BranchPrivate::BranchPrivate(Branch* pub, const Git::Reference& ref) - : RefPrivate(pub, BranchType, ref) - , mHasUpstream(false) - , mAheadCount(0) - , mBehindCount(0) - { - } - - ObjTypes BranchPrivate::objType() const - { - return BranchObject; - } - - void BranchPrivate::postCreation() - { - if (!repoEventsBlocked()) { - Events::self()->branchCreated(repository(), pub()); - } - - RefPrivate::postCreation(); - } - - void BranchPrivate::preTerminate() - { - if (!repoEventsBlocked()) { - Events::self()->branchAboutToBeDeleted(repository(), pub()); - } - - RefPrivate::preTerminate(); - } - - void BranchPrivate::dumpSelf(Internal::Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("Branch 0x%1 - %2")) - .arg(quintptr(mPub),0,16) - .arg(mName)); - } - - QString BranchPrivate::objectTypeName() const - { - return QStringLiteral("Branch"); - } - - void BranchPrivate::emitMoved() - { - if (!repoEventsBlocked()) { - Events::self()->refMoved(mRepo, pub()); - Events::self()->branchMoved(mRepo, pub()); - } - } - - bool BranchPrivate::refreshDetails(const Git::Reference& ref) - { - - return RefPrivate::refreshDetails(ref); - } - - bool BranchPrivate::inherits(ObjTypes type) const - { - return type == BranchObject || RefPrivate::inherits(type); - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/CollectionNode.cpp b/Libs/libMacGitverCore/RepoMan/CollectionNode.cpp deleted file mode 100644 index 8f703ffb..00000000 --- a/Libs/libMacGitverCore/RepoMan/CollectionNode.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include - -#include "libHeavenIcons/IconRef.hpp" - -#include "CollectionNode.hpp" - -#include "Private/Dumper.hpp" -#include "Private/CollectionNodePrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - CollectionNode::CollectionNode(CollectionTypes _ctype, Base* _parent) - : Base(*new CollectionNodePrivate(this, _ctype)) - { - RM_D(CollectionNode); - d->linkToParent(_parent); - } - - - CollectionTypes CollectionNode::collectionType() const - { - RM_CD(CollectionNode); - return d->ctype; - } - - QString CollectionNode::collectionTypeName() const - { - RM_CD(CollectionNode); - - switch (d->ctype) { - case ctBranches: return tr("Branches"); - case ctTags: return tr("Tags"); - case ctNamespaces: return tr("Namespaces"); - case ctNotes: return tr("Notes"); - default: return QString(); - } - } - - //-- CollectionNodePrivate --------------------------------------------------------------------- - - CollectionNodePrivate::CollectionNodePrivate(CollectionNode* _pub, CollectionTypes _ctype) - : BasePrivate(_pub) - , ctype(_ctype) - { - } - - ObjTypes CollectionNodePrivate::objType() const - { - return CollectionNodeObject; - } - - QString CollectionNodePrivate::displayName() const - { - return pub()->collectionTypeName(); - } - - void CollectionNodePrivate::dumpSelf(Internal::Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("Collection '%2' 0x%1")) - .arg(quintptr(mPub),0,16) - .arg(displayName())); - } - - bool CollectionNodePrivate::refreshSelf() - { - return true; - } - - void CollectionNodePrivate::postCreation() - { - BasePrivate::postCreation(); - } - - void CollectionNodePrivate::preTerminate() - { - BasePrivate::preTerminate(); - } - - QString CollectionNodePrivate::objectTypeName() const - { - return QStringLiteral("CollectionNode"); - } - - Heaven::IconRef CollectionNodePrivate::icon(bool small) const - { - QString size = small ? QStringLiteral("@16") : QStringLiteral("@24"); - QString s; - - switch (ctype) { - case ctBranches: s = QStringLiteral("Branches"); break; - case ctTags: s = QStringLiteral("Tags"); break; - case ctNotes: s = QStringLiteral("Notes"); break; - case ctNamespaces: s = QStringLiteral("Namespaces"); break; - default: return Heaven::IconRef(); - } - - return Heaven::IconRef::fromString(QChar(L'#') % s % size); - } - - bool CollectionNodePrivate::inherits(ObjTypes type) const - { - return type == CollectionNodeObject || BasePrivate::inherits(type); - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/Events.cpp b/Libs/libMacGitverCore/RepoMan/Events.cpp deleted file mode 100644 index 9a96bb03..00000000 --- a/Libs/libMacGitverCore/RepoMan/Events.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include "RepoMan/Events.hpp" - -namespace RM -{ - - /** - * @class EventsInterface - * @brief Interface that receives all RepoMan events - * - * All pure virtual methods in this interface represent events from the RepoMan. - * - * Each of these events can be connected to individually via Qt's SIGNAL/SLOT mechanism on the - * MacGitver::repoMan() singleton. - * - * You can also write an implementation of the whole interface and register it through the - * Events singleton. We're doing that in the unit tests - and probably will do it in a - * Heaven::View in order to display the repository events. - * - * @fn EventsInterface::repositoryOpened(Repo* repo) - * @brief Sent after a repository is opened - * - * This is an administrative event. It implies no actual change to the underlying repository. - * - * @param[in] repo The repository that was opened - * - * - * @fn EventsInterface::repositoryAboutToClose(Repo* repo) - * @brief Sent before a repository will be closed - * - * This is an administrative event. It implies no actual change to the underlying repository. - * - * @param[in] repo The repository that is about to be closed - * - * - * @fn EventsInterface::repositoryActivated(Repo* repo) - * @brief Sent after a repository was activated - * - * This is an administrative event. It implies no actual change to the underlying repository. - * - * @param[in] repo The repository that became the active one - * - * - * @fn EventsInterface::repositoryDeactivated(Repo* repo) - * @brief Sent after a repository was deactivated - * - * This is an administrative event. It implies no actual change to the underlying repository. - * - * @param[in] repo The repository that was activated - * - * - * @fn EventsInterface::repositoryStateChanged(Repo* repo) - * @brief Sent after a change in a repository's state was detected - * - * Transitions between "normal", "rebasing", "merging" etc. are detected. - * - * @param[in] repo The repository whose state changed - * - * @fn EventsInterface::refTreeNodeCreated(Repo* repo, RefTreeNode* node) - * @brief Sent when a new tree node in a ref tree was created - * - * This is a virtual event. It is artificially created. - * - * @param[in] repo The repository for which a ref tree node was created - * @param[in] node The node that was created - * - * - * @fn EventsInterface::refTreeNodeAboutToBeRemoved(Repo* repo, RefTreeNode* node) - * @brief Sent before a tree node in a ref tree will be removed - * - * This is a virtual event. It is artificially created. - * - * @param[in] repo The repository for which a ref tree node will be removed - * @param[in] node The node that will be removed - * - * - * @fn EventsInterface::refCreated(Repo* repo, Ref* ref) - * @brief Sent after a reference was created - * - * @param[in] repo The affected repository - * @param[in] ref The newly created reference - * - * @fn EventsInterface::refAboutToBeRemoved(Repo* repo, Ref* ref) - * @brief Sent before a reference is about to be removed - * - * The reference is most probably already physically removed. This event is sent before it is - * removed from RepoMan's data model. - * - * @param[in] repo The affected repository - * @param[in] ref The reference that will be removed - * - * - * @fn EventsInterface::refMoved(Repo* repo, Ref* ref) - * @brief Sent when either the target id or the symbolic target of a reference changed. - * - * The reference is most probably already physically moved. This event is sent when the change - * is discovered by the RepoMan. - * - * @param[in] repo The affected repository - * @param[in] ref The reference that will move - * - * - * @fn EventsInterface::refHeadDetached(Repo* repo, Ref* ref) - * @brief Sent after the HEAD reference got into a detached state - * - * This event will be sent when RepoMan detected that the HEAD reference has been set to a - * detached state. - * - * This will happen constantly during a rebase action and also happens after checking out a - * given SHA1 or a tag. - * - * @param[in] repo The affected repository - * @param[in] ref The HEAD reference that got detached - * - */ - - Events::Events() - { - } - - Events* Events::sSelf = NULL; - - Events* Events::self() - { - if (sSelf == NULL) { - sSelf = new Events; - } - return sSelf; - } - - void Events::addReceiver(EventsInterface* ev) - { - self()->mEvents.insert(ev); - } - - void Events::delReceiver(EventsInterface* ev) - { - self()->mEvents.remove(ev); - } - - void Events::repositoryOpened(Repo* repo) - { - foreach (EventsInterface* ei, mEvents) { - ei->repositoryOpened(repo); - } - } - - void Events::repositoryAboutToClose(Repo* repo) - { - foreach (EventsInterface* ei, mEvents) { - ei->repositoryAboutToClose(repo); - } - } - - void Events::repositoryActivated(Repo* repo) - { - foreach (EventsInterface* ei, mEvents) { - ei->repositoryActivated(repo); - } - } - - void Events::repositoryDeactivated(Repo* repo) - { - foreach (EventsInterface* ei, mEvents) { - ei->repositoryDeactivated(repo); - } - } - - void Events::objectCreated(Repo* repo, Base* object) - { - foreach (EventsInterface* ei, mEvents) { - ei->objectCreated(repo, object); - } - } - - void Events::objectAboutToBeDeleted(Repo* repo, Base* object) - { - foreach (EventsInterface* ei, mEvents) { - ei->objectAboutToBeDeleted(repo, object); - } - } - - void Events::refTreeNodeCreated(Repo* repo, RefTreeNode* node) - { - foreach (EventsInterface* ei, mEvents) { - ei->refTreeNodeCreated(repo, node); - } - } - - void Events::refTreeNodeAboutToBeDeleted(Repo* repo, RefTreeNode* node) - { - foreach (EventsInterface* ei, mEvents) { - ei->refTreeNodeAboutToBeDeleted(repo, node); - } - } - - void Events::refCreated(Repo* repo, Ref* ref) - { - foreach (EventsInterface* ei, mEvents) { - ei->refCreated(repo, ref); - } - } - - void Events::refAboutToBeDeleted(Repo* repo, Ref* ref) - { - foreach (EventsInterface* ei, mEvents) { - ei->refAboutToBeDeleted(repo, ref); - } - } - - void Events::refMoved(Repo* repo, Ref* ref) - { - foreach (EventsInterface* ei, mEvents) { - ei->refMoved(repo, ref); - } - } - - void Events::refHeadDetached(Repo* repo, Ref* ref) - { - foreach (EventsInterface* ei, mEvents) { - ei->refHeadDetached(repo, ref); - } - } - - void Events::tagCreated(Repo* repo, Tag* tag) - { - foreach (EventsInterface* ei, mEvents) { - ei->tagCreated(repo, tag); - } - } - - void Events::tagAboutToBeDeleted(Repo* repo, Tag* tag) - { - foreach (EventsInterface* ei, mEvents) { - ei->tagAboutToBeDeleted(repo, tag); - } - } - - void Events::branchCreated(Repo* repo, Branch* branch) - { - foreach (EventsInterface* ei, mEvents) { - ei->branchCreated(repo, branch); - } - } - - void Events::branchAboutToBeDeleted(Repo* repo, Branch* branch) - { - foreach (EventsInterface* ei, mEvents) { - ei->branchAboutToBeDeleted(repo, branch); - } - } - - void Events::branchMoved(Repo* repo, Branch* branch) - { - foreach (EventsInterface* ei, mEvents) { - ei->branchMoved(repo, branch); - } - } - - void Events::branchUpstreamChanged(Repo* repo, Branch* branch) - { - foreach (EventsInterface* ei, mEvents) { - ei->branchUpstreamChanged(repo, branch); - } - } - - void Events::namespaceCreated(Repo* repo, Namespace* nameSpace) - { - foreach (EventsInterface* ei, mEvents) { - ei->namespaceCreated(repo, nameSpace); - } - } - - void Events::namespaceAboutToBeDeleted(Repo* repo, Namespace* nameSpace) - { - foreach (EventsInterface* ei, mEvents) { - ei->namespaceAboutToBeDeleted(repo, nameSpace); - } - } - - void Events::refLogChanged(Repo* repo, RefLog* reflog) - { - foreach (EventsInterface* ei, mEvents) { - ei->refLogChanged(repo, reflog); - } - } - - void Events::refLogNewEntry(Repo* repo, RefLog* reflog) - { - foreach (EventsInterface* ei, mEvents) { - ei->refLogNewEntry(repo, reflog); - } - } - - void Events::stageCreated(Repo* repo, Ref* ref) - { - foreach (EventsInterface* ei, mEvents) { - ei->stageCreated(repo, ref); - } - } - - void Events::stageAboutToBeDeleted(Repo* repo, Ref* ref) - { - foreach (EventsInterface* ei, mEvents) { - ei->stageAboutToBeDeleted(repo, ref); - } - } - - void Events::remoteCreated(Repo* repo, Remote* remote) - { - foreach (EventsInterface* ei, mEvents) { - ei->remoteCreated(repo, remote); - } - } - - void Events::remoteAboutToBeDeleted(Repo* repo, Remote* remote) - { - foreach (EventsInterface* ei, mEvents) { - ei->remoteAboutToBeDeleted(repo, remote); - } - } - - void Events::remoteModified(Repo* repo, Remote* remote) - { - foreach (EventsInterface* ei, mEvents) { - ei->remoteModified(repo, remote); - } - } - - void Events::submoduleCreated(Repo* repo, Submodule* submodule) - { - foreach (EventsInterface* ei, mEvents) { - ei->submoduleCreated(repo, submodule); - } - } - - void Events::submoduleAboutToBeDeleted(Repo* repo, Submodule* submodule) - { - foreach (EventsInterface* ei, mEvents) { - ei->submoduleAboutToBeDeleted(repo, submodule); - } - } - - void Events::submoduleMoved(Repo* repo, Submodule* submodule) - { - foreach (EventsInterface* ei, mEvents) { - ei->submoduleMoved(repo, submodule); - } - } - - void Events::repositoryStateChanged(Repo* repo) - { - foreach (EventsInterface* ei, mEvents) { - ei->repositoryStateChanged(repo); - } - } - - void Events::indexUpdated(Repo* repo) - { - foreach (EventsInterface* ei, mEvents) { - ei->indexUpdated(repo); - } - } - - void Events::workTreeUpdated(Repo* repo) - { - foreach (EventsInterface* ei, mEvents) { - ei->workTreeUpdated(repo); - } - } - - -} diff --git a/Libs/libMacGitverCore/RepoMan/Events.hpp b/Libs/libMacGitverCore/RepoMan/Events.hpp deleted file mode 100644 index 5f30ee04..00000000 --- a/Libs/libMacGitverCore/RepoMan/Events.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#pragma once - -#include - -#include "libMacGitverCore/MacGitverApi.hpp" - -namespace RM -{ - - class Base; - class Namespace; - class Repo; - class Ref; - class Remote; - class Submodule; - class RefTreeNode; - class RefLog; - class Branch; - class Tag; - - class MGV_CORE_API EventsInterface - { - public: - virtual ~EventsInterface() {} - - public: - virtual void repositoryOpened(Repo* repo) = 0; - virtual void repositoryAboutToClose(Repo* repo) = 0; - virtual void repositoryActivated(Repo* repo) = 0; - virtual void repositoryDeactivated(Repo* repo) = 0; - - virtual void objectCreated(Repo* repo, Base* object) = 0; - virtual void objectAboutToBeDeleted(Repo* repo, Base* object) = 0; - - virtual void refTreeNodeCreated(Repo* repo, RefTreeNode* node) = 0; - virtual void refTreeNodeAboutToBeDeleted(Repo* repo, RefTreeNode* node) = 0; - - virtual void refCreated(Repo* repo, Ref* ref) = 0; - virtual void refAboutToBeDeleted(Repo* repo, Ref* ref) = 0; - virtual void refMoved(Repo* repo, Ref* ref) = 0; - virtual void refHeadDetached(Repo* repo, Ref* ref) = 0; - - virtual void tagCreated(Repo* repo, Tag* tag) = 0; - virtual void tagAboutToBeDeleted(Repo* repo, Tag* tag) = 0; - - virtual void branchCreated(Repo* repo, Branch* branch) = 0; - virtual void branchAboutToBeDeleted(Repo* repo, Branch* branch) = 0; - virtual void branchMoved(Repo* repo, Branch* branch) = 0; - virtual void branchUpstreamChanged(Repo* repo, Branch* branch) = 0; - - virtual void namespaceCreated(Repo* repo, Namespace* nameSpace) = 0; - virtual void namespaceAboutToBeDeleted(Repo* repo, Namespace* nameSpace) = 0; - - virtual void refLogChanged(Repo* repo, RefLog* reflog) = 0; - virtual void refLogNewEntry(Repo* repo, RefLog* reflog) = 0; - - virtual void stageCreated(Repo* repo, Ref* ref) = 0; - virtual void stageAboutToBeDeleted(Repo* repo, Ref* ref) = 0; - - virtual void remoteCreated(Repo* repo, Remote* remote) = 0; - virtual void remoteAboutToBeDeleted(Repo* repo, Remote* remote) = 0; - virtual void remoteModified(Repo* repo, Remote* remote) = 0; - - virtual void submoduleCreated(Repo* repo, Submodule* submodule) = 0; - virtual void submoduleAboutToBeDeleted(Repo* repo, Submodule* submodule) = 0; - virtual void submoduleMoved(Repo* repo, Submodule* submodule) = 0; - - virtual void repositoryStateChanged(Repo* repo) = 0; - virtual void indexUpdated(Repo* repo) = 0; - virtual void workTreeUpdated(Repo* repo) = 0; - }; - - class MGV_CORE_API Events // : public EventsInterface - { - private: - Events(); - - public: - static Events* self(); - static void addReceiver(EventsInterface* ev); - static void delReceiver(EventsInterface* ev); - - private: - QSet< EventsInterface* > mEvents; - static Events* sSelf; - - public: - void repositoryOpened(Repo* repo); - void repositoryAboutToClose(Repo* repo); - void repositoryActivated(Repo* repo); - void repositoryDeactivated(Repo* repo); - void objectCreated(Repo* repo, Base* object); - void objectAboutToBeDeleted(Repo* repo, Base* object); - void refTreeNodeCreated(Repo* repo, RefTreeNode* node); - void refTreeNodeAboutToBeDeleted(Repo* repo, RefTreeNode* node); - void refCreated(Repo* repo, Ref* ref); - void refAboutToBeDeleted(Repo* repo, Ref* ref); - void refMoved(Repo* repo, Ref* ref); - void refHeadDetached(Repo* repo, Ref* ref); - void tagCreated(Repo* repo, Tag* tag); - void tagAboutToBeDeleted(Repo* repo, Tag* tag); - void branchCreated(Repo* repo, Branch* branch); - void branchAboutToBeDeleted(Repo* repo, Branch* branch); - void branchMoved(Repo* repo, Branch* branch); - void branchUpstreamChanged(Repo* repo, Branch* branch); - void namespaceCreated(Repo* repo, Namespace* nameSpace); - void namespaceAboutToBeDeleted(Repo* repo, Namespace* nameSpace); - void refLogChanged(Repo* repo, RefLog* reflog); - void refLogNewEntry(Repo* repo, RefLog* reflog); - void stageCreated(Repo* repo, Ref* ref); - void stageAboutToBeDeleted(Repo* repo, Ref* ref); - void remoteCreated(Repo* repo, Remote* remote); - void remoteAboutToBeDeleted(Repo* repo, Remote* remote); - void remoteModified(Repo* repo, Remote* remote); - void submoduleCreated(Repo* repo, Submodule* submodule); - void submoduleAboutToBeDeleted(Repo* repo, Submodule* submodule); - void submoduleMoved(Repo* repo, Submodule* submodule); - void repositoryStateChanged(Repo* repo); - void indexUpdated(Repo* repo); - void workTreeUpdated(Repo* repo); - }; - -} diff --git a/Libs/libMacGitverCore/RepoMan/Private/BasePrivate.hpp b/Libs/libMacGitverCore/RepoMan/Private/BasePrivate.hpp deleted file mode 100644 index ea703066..00000000 --- a/Libs/libMacGitverCore/RepoMan/Private/BasePrivate.hpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#pragma once - -#include "RepoMan/Base.hpp" - -#define RM_D(CLASS) Internal::CLASS##Private* d = \ - static_cast(mData) - -#define RM_CD(CLASS) const Internal::CLASS##Private* d = \ - static_cast(mData) - -#define RM_P(CLASS) CLASS* p = \ - static_cast(mPub) - -#define RM_CP(CLASS) const CLASS* p = \ - static_cast(mPub) - -namespace RM -{ - - namespace Internal - { - - class Dumper; - - class BasePrivate - { - protected: - BasePrivate(Base* pub); - - public: - virtual ~BasePrivate(); - - public: - Base* mPub; - Repo* mRepo; - BasePrivate* mParentObj; - Base::Set mChildren; - - public: - template< class T > T* pub() - { - return static_cast(mPub); - } - - template< class T > const T* pub() const - { - return static_cast(mPub); - } - - public: - void dumpRecursive(Dumper& dumper) const; - - void terminateObject(); - void linkToParent(Base* parent); - void unlinkFromParent(); - void addChildObject(Base *object); - void removeChildObject(Base* object); - Repo* repository(); - - virtual Repo* searchRepository(); - - void refresh(); - bool repoEventsBlocked(); - - Base* findRefParent(const QStringList& scopes, bool create); - RefTreeNode* findRefTreeNode(const QStringList& scopes, bool create); - - CollectionNode* getOrCreateCollection(CollectionTypes ctype); - - template< class T > static typename T::Private* dataOf(Base* b) - { - BasePrivate* p = b->mData; - if (p->objType() != ObjTypes(T::StaticObjectType)) { - return NULL; - } - return static_cast(p); - } - - public: - virtual QString displayName() const; - virtual QString objectTypeName() const = 0; - virtual Heaven::IconRef icon(bool small) const; - virtual bool refreshSelf() = 0; - virtual void postRefresh(); - virtual void preRefreshChildren(); - virtual void postRefreshChildren(); - virtual void postCreation(); - virtual void preTerminate(); - virtual bool refreshCheckDispensable(); - virtual bool inherits(ObjTypes type) const; - virtual ObjTypes objType() const = 0; - virtual void dumpSelf(Dumper& dumper) const = 0; - }; - - inline Repo* BasePrivate::repository() - { - return mRepo; - } - - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/RefLog.cpp b/Libs/libMacGitverCore/RepoMan/RefLog.cpp deleted file mode 100644 index 443fbc5e..00000000 --- a/Libs/libMacGitverCore/RepoMan/RefLog.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include "RefLog.hpp" - -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/RefLogPrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - RefLog::RefLog(Base* _parent) - : Base(*new RefLogPrivate(this)) - { - RM_D(RefLog); - d->linkToParent(_parent); - } - - //-- RefLogPrivate ----------------------------------------------------------------------------- - - RefLogPrivate::RefLogPrivate(RefLog* _pub) - : BasePrivate(_pub) - { - } - - ObjTypes RefLogPrivate::objType() const - { - return RefLogObject; - } - - void RefLogPrivate::dumpSelf(Internal::Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("RefLog 0x%1")) - .arg(quintptr(mPub),0,16)); - } - - void RefLogPrivate::postCreation() - { - BasePrivate::postCreation(); - } - - void RefLogPrivate::preTerminate() - { - // What to do? We don't send Ref-Log-Deleted events - BasePrivate::preTerminate(); - } - - bool RefLogPrivate::refreshSelf() - { - return true; - } - - QString RefLogPrivate::objectTypeName() const - { - return QStringLiteral("RefLog"); - } - - bool RefLogPrivate::inherits(ObjTypes type) const - { - return type == RefLogObject || BasePrivate::inherits(type); - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/RefTreeNode.cpp b/Libs/libMacGitverCore/RepoMan/RefTreeNode.cpp deleted file mode 100644 index 4fae6a5a..00000000 --- a/Libs/libMacGitverCore/RepoMan/RefTreeNode.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include "RefTreeNode.hpp" -#include "Events.hpp" -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/RefTreeNodePrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - RefTreeNode::RefTreeNode(Base* _parent, const QString& _name) - : Base(*new RefTreeNodePrivate(this, _name)) - { - RM_D(RefTreeNode); - d->linkToParent(_parent); - } - - QString RefTreeNode::name() const - { - RM_D(RefTreeNode); - - return d->name; - } - - //-- RefTreeNodePrivate ------------------------------------------------------------------------ - - RefTreeNodePrivate::RefTreeNodePrivate(RefTreeNode* _pub, const QString& _name) - : BasePrivate(_pub) - , name(_name) - { - } - - ObjTypes RefTreeNodePrivate::objType() const - { - return RefTreeNodeObject; - } - - void RefTreeNodePrivate::dumpSelf(Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("RefTreeNode 0x%1 [%2]")) - .arg(quintptr(mPub),0,16) - .arg(name)); - } - - void RefTreeNodePrivate::postCreation() - { - if (!repoEventsBlocked()) { - Events::self()->refTreeNodeCreated(repository(), pub()); - } - - BasePrivate::postCreation(); - } - - void RefTreeNodePrivate::preTerminate() - { - if (!repoEventsBlocked()) { - Events::self()->refTreeNodeAboutToBeDeleted(repository(), pub()); - } - - BasePrivate::preTerminate(); - } - - QString RefTreeNodePrivate::displayName() const - { - return name; - } - - bool RefTreeNodePrivate::refreshSelf() - { - // We don't have anything to refresh - we're purely virutual - return true; - } - - bool RefTreeNodePrivate::refreshCheckDispensable() - { - return mChildren.isEmpty(); - } - - QString RefTreeNodePrivate::objectTypeName() const - { - return QStringLiteral("RefTreeNode"); - } - - bool RefTreeNodePrivate::inherits(ObjTypes type) const - { - return type == RefTreeNodeObject || BasePrivate::inherits(type); - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/Remote.cpp b/Libs/libMacGitverCore/RepoMan/Remote.cpp deleted file mode 100644 index 7a402400..00000000 --- a/Libs/libMacGitverCore/RepoMan/Remote.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include "libGitWrap/Result.hpp" - -#include "Repo.hpp" -#include "Remote.hpp" -#include "Events.hpp" -#include "CollectionNode.hpp" - -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/RemotePrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - Remote::Remote(const Git::Remote& gitObj, Base* _parent) - : Base(*new RemotePrivate(this, gitObj)) - { - RM_D(Remote); - - d->linkToParent(_parent); - } - - Git::Remote Remote::gitObject() - { - Git::Result r; - return repository()->gitRepo().remote(r, name()); - } - - QString Remote::name() const - { - RM_D(Remote); - - return d->name; - } - - CollectionNode* Remote::branches() - { - RM_D(Remote); - - - // ### We don't use this when filling up the branches, yet. - return d->getOrCreateCollection(ctBranches); - } - - //-- RemotePrivate ----------------------------------------------------------------------------- - - RemotePrivate::RemotePrivate(Remote* _pub, const Git::Remote& _obj) - : BasePrivate(_pub) - { - name = _obj.name(); - } - - ObjTypes RemotePrivate::objType() const - { - return RemoteObject; - } - - void RemotePrivate::dumpSelf(Internal::Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("Remote %2 0x%1")) - .arg(quintptr(mPub),0,16) - .arg(name)); - } - - void RemotePrivate::postCreation() - { - if (!repoEventsBlocked()) { - Events::self()->remoteCreated(repository(), pub()); - } - - BasePrivate::postCreation(); - } - - void RemotePrivate::preTerminate() - { - if (!repoEventsBlocked()) { - Events::self()->remoteAboutToBeDeleted(repository(), pub()); - } - - BasePrivate::preTerminate(); - } - - QString RemotePrivate::displayName() const - { - return name; - } - - - bool RemotePrivate::refreshSelf() - { - return true; - } - - QString RemotePrivate::objectTypeName() const - { - return QStringLiteral("Remote"); - } - - bool RemotePrivate::inherits(ObjTypes type) const - { - return type == RemoteObject || BasePrivate::inherits(type); - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/Remote.hpp b/Libs/libMacGitverCore/RepoMan/Remote.hpp deleted file mode 100644 index d47d5e6c..00000000 --- a/Libs/libMacGitverCore/RepoMan/Remote.hpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#pragma once - -#include "libGitWrap/Remote.hpp" - -#include "Base.hpp" - -namespace RM -{ - - namespace Internal - { - class RemotePrivate; - } - - class MGV_CORE_API Remote : public Base - { - public: - enum { StaticObjectType = RemoteObject }; - typedef Internal::RemotePrivate Private; - typedef QSet< Remote* > Set; - typedef QVector< Remote* > List; - - public: - Remote(const Git::Remote& gitObj, Base* parent); - - public: - GW_DEPRECATED - Git::Remote gitObject(); - QString name() const; - CollectionNode* branches(); - }; - -} diff --git a/Libs/libMacGitverCore/RepoMan/Repo.cpp b/Libs/libMacGitverCore/RepoMan/Repo.cpp deleted file mode 100644 index 6a62258a..00000000 --- a/Libs/libMacGitverCore/RepoMan/Repo.cpp +++ /dev/null @@ -1,758 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include -#include - -#include "libGitWrap/Reference.hpp" -#include "libGitWrap/ObjectId.hpp" -#include "libGitWrap/RefName.hpp" -#include "libGitWrap/Submodule.hpp" - -#include "libMacGitverCore/App/MacGitver.hpp" - -#include "RepoMan/Events.hpp" -#include "RepoMan/Repo.hpp" -#include "RepoMan/RepoMan.hpp" -#include "RepoMan/Head.hpp" -#include "RepoMan/Remote.hpp" -#include "RepoMan/Namespace.hpp" -#include "RepoMan/Ref.hpp" -#include "RepoMan/Tag.hpp" -#include "RepoMan/Branch.hpp" -#include "RepoMan/Submodule.hpp" - -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/RepoPrivate.hpp" -#include "RepoMan/Private/RemotePrivate.hpp" -#include "RepoMan/Private/CollectionNodePrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - Repo::Repo(RepoPrivate& _d) - : Base(_d) - { - } - - Repo::Repo(const Git::Repository& repo, Base* parent) - : Base( *new RepoPrivate(this, repo) ) - { - RM_D(Repo); - - d->linkToParent(parent); - d->refresh(); - - d->mIsInitializing = false; - } - - Repo::~Repo() - { - } - - Git::Repository Repo::gitRepo() - { - RM_D(Repo); - return d->gitRepo(true); - } - - Git::Repository Repo::gitLoadedRepo() - { - RM_D(Repo); - return d->gitRepo(); - } - - QString Repo::path() const - { - RM_CD(Repo); - - return d->mPath; - } - - bool Repo::isSubModule() const - { - RM_CD(Repo); - - return d->mIsSubModule; - } - - bool Repo::isBare() const - { - RM_CD(Repo); - - return d->mIsBare; - } - - bool Repo::isLoaded() const - { - RM_CD(Repo); - - return d->mIsLoaded; - } - - bool Repo::isActive() const - { - RM_CD(Repo); - - return d->mIsActive; - } - - /** - * @brief Are we in initialization phase? - * - * @return `true` if we're still doing an initial seed with repository objects. In this - * case no events for new or changed objects shall be sent out to any listeners. - * - */ - bool Repo::isInitializing() const - { - RM_CD(Repo); - - return d->mIsInitializing; - } - - Repo* Repo::parentRepository() - { - Base* p = parentObject(); - - if (!p) { - return NULL; - } - - if (p->inheritsRepoManType(RepoObject)) { - return static_cast(p); - } - - return NULL; - } - - Repo::Set Repo::submodules() const - { - return childObjects(); - } - - void Repo::activated() - { - // ### Should be very private - RM_D(Repo); - Q_ASSERT(!d->mIsActive); - - if (d->mUnloadTimer) { - d->mUnloadTimer->stop(); - d->mUnloadTimer->deleteLater(); - d->mUnloadTimer = NULL; - } - - d->mIsActive = true; - } - - void Repo::deactivated() - { - // ### Should be very private - RM_D(Repo); - Q_ASSERT(d->mIsActive); - - Q_ASSERT(!d->mUnloadTimer); - d->mUnloadTimer = new QTimer(this); - connect(d->mUnloadTimer, SIGNAL(timeout()), this, SLOT(unloadTimer())); - d->mUnloadTimer->setInterval(15 * 60 * 1000); // quarter of an hour - d->mUnloadTimer->start(); - - d->mIsActive = false; - } - - QString Repo::displayAlias() const - { - RM_CD(Repo); - - return d->mDisplayAlias; - } - - void Repo::setDisplayAlias(const QString& alias) - { - RM_D(Repo); - - if (d->mDisplayAlias != alias) { - d->mDisplayAlias = alias; - // ###REPOMAN Create new Event "RepoAliasChanged" - // emit aliasChanged(alias); - } - } - - void Repo::unloadTimer() - { - RM_D(Repo); - d->unload(); - } - - void Repo::close() - { - RM_D(Repo); - - if (d->mIsActive) { - MacGitver::repoMan().activate(NULL); - } - - Events::self()->repositoryAboutToClose(this); - - foreach (Repo* child, submodules()) { - child->close(); - } - - d->terminateObject(); - } - - QString Repo::branchDisplay() const - { - // TODO: This method is totally wrong placed here - RM_D(Repo); - - if (d->mIsLoaded && d->mHead) { - - if (d->mHead->isDetached()) { - return tr("detached at %1" ).arg(d->mHead->detachedId().toString()); - } - - if (d->mHead->isUnborn()) { - return tr("Branch yet to be born"); - } - - return tr("%1" ).arg(d->mHead->symbolicName().mid(11)); - } - return tr("<unknown>"); - } - - Ref* Repo::findReference(const Git::Reference& ref) - { - RM_D(Repo); - return d->findReference(ref, false); - } - - Ref* Repo::findReference(const QString &fqrn) - { - RM_D(Repo); - return d->findReference(fqrn, false); - } - - Remote* Repo::findRemote(const Git::Remote& remote) - { - RM_D(Repo); - return d->findRemote(remote, false); - } - - Remote* Repo::findRemote(const QString& remoteName) - { - RM_D(Repo); - return d->findRemote(remoteName, false); - } - - Namespace* Repo::findNamespace(const QStringList& namespaces) - { - RM_D( Repo ); - return d->findNamespace(namespaces); - } - - Namespace* Repo::findNamespace(const QString& nsFullName) - { - RM_D( Repo ); - return d->findNamespace(nsFullName); - } - - Head* Repo::head() const - { - RM_CD(Repo); - return d->mHead; - } - - /** - * @brief Get this repository's collection of branches - * - * @return A CollectionNode whose children are the branches included in this repository. - * - * Branches are references matching the regular expression `^refs/heads/.*$`. Branches may be - * scoped in which case they are subdivided into RefTreeNode objects. - * - */ - CollectionNode* Repo::branches() - { - RM_D( Repo ); - return d->getOrCreateCollection( ctBranches ); - } - - /** - * @brief Get this repository's collection of tags - * - * @return A CollectionNode whose children are the tags included in this repository. - * - * Tags are references matching the regular expression `^refs/tags/.*$`. Tags may be scoped in - * which case they are subdivided into RefTreeNode objects. - * - */ - CollectionNode* Repo::tags() - { - RM_D( Repo ); - return d->getOrCreateCollection( ctTags ); - } - - /** - * @brief Get this repository's collection of namespaces - * - * @return A CollectionNode whose children are the 1st level namespaces included in this - * repository. - * - */ - CollectionNode* Repo::namespaces() - { - RM_D(Repo); - return d->getOrCreateCollection(ctNamespaces); - } - - /** - * @brief Get this repository's collection of notes - * - * @return A CollectionNode object whose children are the notes included in this repository. - * - * Notes are refs matching the regular expression `^refs/notes/.*$`. Notes may be scoped, in - * which case they are subdivided into RefTreeNode objects. - * - */ - CollectionNode* Repo::notes() - { - RM_D(Repo); - return d->getOrCreateCollection(ctNotes); - } - - //-- RepoPrivate ------------------------------------------------------------------------------- - - RepoPrivate::RepoPrivate(Repo* pub, const Git::Repository& repo) - : BasePrivate( pub ) - { - mRepo = repo; - mHead = NULL; - mPath = mRepo.workTreePath(); - mIsLoaded = mRepo.isValid(); - mIsActive = false; - mIsBare = mRepo.isValid() && mRepo.isBare(); - mIsSubModule = false; - mIsInitializing = true; - mDisplayAlias = QString(); - mUnloadTimer = NULL; - - if (mPath.endsWith(L'/')) { - mPath = mPath.left(mPath.length() - 1); - } - - findAlias(); - - if (mDisplayAlias.isEmpty()) { - if (mPath.isEmpty()) { - mDisplayAlias = Repo::tr("Unknown Repository"); - } - else { - QStringList sl = mPath.split(QChar(L'/'), QString::SkipEmptyParts); - mDisplayAlias = sl.last(); - } - } - } - - RepoPrivate::~RepoPrivate() - { - RM_P(Repo); - - if (mIsLoaded) { - unload(); - } - - MacGitver::repoMan().internalClosedRepo(p); - } - - void RepoPrivate::load() - { - // ### Unimplemented: RepoPrivate::load() - Q_ASSERT(!mIsLoaded); - } - - void RepoPrivate::unload() - { - if (mIsActive) { - qDebug() << "Unloading active RepoInfo. Will deactivate it first."; - MacGitver::repoMan().activate(NULL); - } - Q_ASSERT(!mIsActive); - - if (mUnloadTimer) { - mUnloadTimer->stop(); - mUnloadTimer->deleteLater(); - mUnloadTimer = NULL; - } - - // ####REPOMAN Do we really need to send out events for Unload/Load? If yes, create - // real events for that! - mIsLoaded = false; - mRepo = Git::Repository(); - } - - - QString RepoPrivate::displayName() const - { - return mDisplayAlias; - } - - void RepoPrivate::preTerminate() - { - // Do we need to do smth? - } - - void RepoPrivate::scanSubmodules() - { - RM_P(Repo); - - Git::Repository repo = gitRepo(true); - if (!repo.isValid()) { - return; - } - - Git::Result r; - Git::Submodule::List subs = repo.submodules( r ); - if (!r) { - return; - } - - Repo::Set oldSubmodules = pub()->submodules(); - - foreach (Git::Submodule sub, subs) { - Git::Result child; - Git::Repository subRepo = sub.subRepository(child); - if (!child) { - continue; - } - Q_ASSERT(subRepo.isValid()); - - Repo* subInfo = NULL; - QString path = subRepo.workTreePath(); - - if (path.endsWith(L'/')) { - path = path.left(path.length() - 1); - } - - subInfo = repoByPath(path, true); - if (!subInfo) { - subInfo = new Submodule(subRepo, p); - } - else { - oldSubmodules.remove(subInfo); - } - } - - foreach(Repo* repo, oldSubmodules) { - dataOf(repo)->terminateObject(); - } - } - - void RepoPrivate::findAlias() - { - // ### Unimplemented: RepoPrivate::findAlias() - } - - bool RepoPrivate::refreshSelf() - { - if (!mIsLoaded) { - // In case we're not loaded, just return and do nothing. - return true; - } - - if (!mHead) { - RM_P(Repo); - mHead = new Head(mRepo, p); - } - - return true; - } - - void RepoPrivate::postRefreshChildren() - { - if (!mIsLoaded) { - // In case we're not loaded, just return and do nothing. - return; - } - - Git::Result r; - Git::Remote::List remotes = mRepo.allRemotes(r); - if (r) { - foreach (const Git::Remote& remote, remotes) { - findRemote(remote, true); - } - } - - Git::ReferenceList refs = mRepo.allReferences(r); - if (r) { - foreach (Git::Reference ref, refs) { - findReference(ref, true); - } - } - - scanSubmodules(); - } - - /** - * @brief Get this object's type - * - * @return always RepoObject. - * - */ - ObjTypes RepoPrivate::objType() const - { - return RepoObject; - } - - void RepoPrivate::dumpSelf(Internal::Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("Repository 0x%1 - %02")) - .arg(quintptr(mPub),0,16) - .arg(mIsLoaded ? mRepo.name() - : QStringLiteral(""))); - } - - - Ref* RepoPrivate::findReference(const Git::Reference& ref, bool create) - { - Git::RefName rn = ref.nameAnalyzer(); - return findReference(rn, ref, create); - } - - Ref* RepoPrivate::findReference(const QString& fqrn, bool create) - { - Git::RefName rn(fqrn); - return findReference(rn, Git::Reference(), create); - } - - Ref* RepoPrivate::findReference(Git::RefName& rn, Git::Reference ref, bool create) - { - Base* parent = NULL; - CollectionNode* cn = NULL; - - if (rn.isRemote() && rn.isBranch()) { - Remote* rm = findRemote(rn.remote(), create); - - if (!rm) { - return NULL; - } - - RemotePrivate* rmp = dataOf(rm); - if (!rmp) { - return NULL; - } - - parent = rmp->findRefParent(rn.scopes(), create); - } - else if (rn.isNamespaced()) { - Namespace* ns = findNamespace(rn.namespaces(), create); - - if (!ns) { - return NULL; - } - - if (rn.isBranch()) { - cn = ns->branches(); - } - else if (rn.isTag()) { - cn = ns->tags(); - } - else { - return NULL; - } - - CollectionNodePrivate* cnp = dataOf(cn); - if (!cnp) { - return NULL; - } - - parent = cnp->findRefParent(rn.scopes(), create); - } - else { - if (rn.isBranch()) { - cn = getOrCreateCollection(ctBranches); - } - else if (rn.isTag()) { - cn = getOrCreateCollection(ctTags); - } - else { - return NULL; - } - - CollectionNodePrivate* cnp = dataOf(cn); - if (!cnp) { - return NULL; - } - - parent = cnp->findRefParent(rn.scopes(), create); - } - - foreach (Ref* rmRef, parent->childObjects()) { - if (rmRef->fullName() == rn.fullName()) { - return rmRef; - } - } - - if (create) { - if ( rn.isBranch() ) { - return new Branch( parent, ref ); - } - else if( rn.isTag() ) { - return new Tag( parent, ref ); - } - else { - qDebug() << "Do not know how to deal with reference:" << rn.fullName(); - return NULL; - } - } - - return NULL; - } - - Remote* RepoPrivate::findRemote(const QString &remoteName, bool create) - { - RM_P(Repo); - - foreach (Remote* remote, p->childObjects()) { - if (remote->name() == remoteName) { - return remote; - } - } - - if (create) { - Git::Result r; - Git::Remote gr = p->gitRepo().remote(r, remoteName); - - if (r && gr.isValid()) { - Remote* remote = new Remote(gr, p); - return remote; - } - } - - return NULL; - } - - Remote* RepoPrivate::findRemote(const Git::Remote &remote, bool create) - { - RM_P( Repo ); - - if (!remote.isValid()) { - return NULL; - } - - QString remoteName = remote.name(); - foreach (Remote* rmRemote, p->childObjects()) { - if (rmRemote->name() == remoteName) { - return rmRemote; - } - } - - if (create) { - Remote* rmRemote = new Remote(remote, p); - return rmRemote; - } - - return NULL; - } - - Namespace* RepoPrivate::findNamespace(const QStringList& _namespaces, bool create) { - - Base* par = getOrCreateCollection(ctNamespaces); - Namespace* child = NULL; - - foreach (QString nsName, _namespaces) { - child = NULL; - - foreach (Namespace* ns, par->childObjects()) { - if (ns->name() == nsName) { - child = ns; - break; - } - } - - if (!child) { - if (create) { - child = new Namespace(par, nsName); - } - else { - return NULL; - } - } - - par = child; - } - - return child; - } - - Namespace* RepoPrivate::findNamespace(const QString& nsFullName, bool create) { - - QStringList nsNames = nsFullName.split(QChar(L'/')); - return findNamespace(nsNames, create); - } - - Repo* RepoPrivate::repoByPath(const QString& basePath, bool searchSubmodules) - { - foreach (Repo* subRepo, mPub->childObjects()) { - - if (subRepo->path() == basePath) { - return subRepo; - } - - if (searchSubmodules) { - if (RepoPrivate* subRepoPriv = dataOf(subRepo)) { - if (Repo* subsubRepo = subRepoPriv->repoByPath(basePath, true)) { - return subsubRepo; - } - } - } - } - - return NULL; - } - - QString RepoPrivate::objectTypeName() const - { - return QStringLiteral("Repo"); - } - - bool RepoPrivate::inherits(ObjTypes type) const - { - return type == RepoObject || BasePrivate::inherits(type); - } - - Repo* RepoPrivate::searchRepository() - { - return static_cast(mPub); - } - - Git::Repository RepoPrivate::gitRepo(bool doLoad) - { - if (!mIsLoaded && doLoad) { - load(); - } - - return mRepo; - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/Repo.hpp b/Libs/libMacGitverCore/RepoMan/Repo.hpp deleted file mode 100644 index 68789b34..00000000 --- a/Libs/libMacGitverCore/RepoMan/Repo.hpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#pragma once - -#include - -class QTimer; - -#include "libGitWrap/Repository.hpp" - -#include "libMacGitverCore/RepoMan/Base.hpp" - -namespace RM -{ - - class RepoMan; - class Head; - - namespace Internal - { - class RepoPrivate; - } - - class MGV_CORE_API Repo : public QObject, public Base - { - friend class RepoMan; - - Q_OBJECT - public: - enum { StaticObjectType = RepoObject }; - typedef Internal::RepoPrivate Private; - typedef QSet< Repo* > Set; - typedef QVector< Repo* > List; - - protected: - Repo(Internal::RepoPrivate& _d); - - public: - Repo(const Git::Repository& repo, Base* parent); - ~Repo(); - - public: - GW_DEPRECATED Git::Repository gitRepo(); - GW_DEPRECATED Git::Repository gitLoadedRepo(); - - bool isSubModule() const; - bool isBare() const; - bool isLoaded() const; - bool isActive() const; - bool isInitializing() const; - - Repo* parentRepository(); - Set submodules() const; - - QString path() const; - - QString displayAlias() const; - void setDisplayAlias( const QString& alias ); - - QString branchDisplay() const; - - void close(); - - Ref* findReference( const Git::Reference& ref); - Ref* findReference( const QString& fqrn); - Remote* findRemote( const Git::Remote& remote); - Remote* findRemote( const QString& remoteName); - Namespace* findNamespace( const QStringList& namespaces); - Namespace* findNamespace( const QString& nsFullName); - - CollectionNode* branches(); - CollectionNode* namespaces(); - CollectionNode* notes(); - CollectionNode* tags(); - Head* head() const; - - private: - void activated(); - void deactivated(); - - private slots: - void unloadTimer(); - }; - -} diff --git a/Libs/libMacGitverCore/RepoMan/RepoMan.hpp b/Libs/libMacGitverCore/RepoMan/RepoMan.hpp deleted file mode 100644 index f9f4f980..00000000 --- a/Libs/libMacGitverCore/RepoMan/RepoMan.hpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#pragma once - -#include - -#include "libGitWrap/Repository.hpp" - -#include "libMacGitverCore/RepoMan/Repo.hpp" -#include "libMacGitverCore/RepoMan/Events.hpp" - -namespace RM -{ - - namespace Internal - { - class RepoManPrivate; - } - - class MGV_CORE_API RepoMan - : public QObject - , public Base - , private EventsInterface - { - Q_OBJECT - public: - enum { StaticObjectType = RepoManagerObject }; - typedef Internal::RepoManPrivate Private; - - public: - RepoMan(); - ~RepoMan(); - - public: - void open(const QString& path); - - void closeAll(); - - Repo* activeRepository(); - void activate(Repo* repository); - - Repo::List repositories() const; - - void internalClosedRepo(Repo* repository); - - public: - static RepoMan& instance(); - void terminate(); - - private slots: - void reactivateWorkaround(); - - signals: - void firstRepositoryOpened(); - void lastRepositoryClosed(); - void repositoryClosed(); - void hasActiveRepositoryChanged(bool hasActiveRepo); - - signals: - void repositoryOpened(RM::Repo* repo); - void repositoryAboutToClose(RM::Repo* repo); - void repositoryActivated(RM::Repo* repo); - void repositoryDeactivated(RM::Repo* repo); - void objectCreated(RM::Repo* repo, RM::Base* object); - void objectAboutToBeDeleted(RM::Repo* repo, RM::Base* object); - void refTreeNodeCreated(RM::Repo* repo, RM::RefTreeNode* node); - void refTreeNodeAboutToBeDeleted(RM::Repo* repo, RM::RefTreeNode* node); - void refCreated(RM::Repo* repo, RM::Ref* ref); - void refAboutToBeDeleted(RM::Repo* repo, RM::Ref* ref); - void refMoved(RM::Repo* repo, RM::Ref* ref); - void refHeadDetached(RM::Repo* repo, RM::Ref* ref); - void tagCreated(RM::Repo* repo, RM::Tag* tag); - void tagAboutToBeDeleted(RM::Repo* repo, RM::Tag* tag); - void branchCreated(RM::Repo* repo, RM::Branch* branch); - void branchAboutToBeDeleted(RM::Repo* repo, RM::Branch* branch); - void branchMoved(RM::Repo* repo, RM::Branch* branch); - void branchUpstreamChanged(RM::Repo* repo, RM::Branch* branch); - void namespaceCreated(RM::Repo* repo, RM::Namespace* nameSpace); - void namespaceAboutToBeDeleted(RM::Repo* repo, RM::Namespace* nameSpace); - void refLogChanged(RM::Repo* repo, RM::RefLog* reflog); - void refLogNewEntry(RM::Repo* repo, RM::RefLog* reflog); - void stageCreated(RM::Repo* repo, RM::Ref* ref); - void stageAboutToBeDeleted(RM::Repo* repo, RM::Ref* ref); - void remoteCreated(RM::Repo* repo, RM::Remote* remote); - void remoteAboutToBeDeleted(RM::Repo* repo, RM::Remote* remote); - void remoteModified(RM::Repo* repo, RM::Remote* remote); - void submoduleCreated(RM::Repo* repo, RM::Submodule* submodule); - void submoduleAboutToBeDeleted(RM::Repo* repo, RM::Submodule* submodule); - void submoduleMoved(RM::Repo* repo, RM::Submodule* submodule); - void repositoryStateChanged(RM::Repo* repo); - void indexUpdated(RM::Repo* repo); - void workTreeUpdated(RM::Repo* repo); - }; - -} diff --git a/Libs/libMacGitverCore/RepoMan/Submodule.cpp b/Libs/libMacGitverCore/RepoMan/Submodule.cpp deleted file mode 100644 index 4f5e148e..00000000 --- a/Libs/libMacGitverCore/RepoMan/Submodule.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include "Submodule.hpp" -#include "Events.hpp" - -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/SubmodulePrivate.hpp" - -namespace RM -{ - using namespace Internal; - - Submodule::Submodule(const Git::Repository& repo, Repo* parent) - : Repo( *new SubmodulePrivate( this, repo ) ) - { - RM_D(Submodule); - - d->mIsSubModule = true; - - setDisplayAlias( repo.name() ); - - d->linkToParent( parent ); - d->refresh(); - - d->mIsInitializing = false; - } - - //-- SubmodulePrivate -------------------------------------------------------------------------- - - SubmodulePrivate::SubmodulePrivate(Submodule* pub, const Git::Repository& repo) - : RepoPrivate( pub, repo ) - { - } - - ObjTypes SubmodulePrivate::objType() const - { - return SubmoduleObject; - } - - void SubmodulePrivate::dumpSelf(Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("Submodule 0x%1")) - .arg(quintptr(mPub),0,16)); - } - - void SubmodulePrivate::postCreation() - { - if (!repoEventsBlocked()) { - Events::self()->submoduleCreated(repository(), pub()); - } - - RepoPrivate::postCreation(); - } - - void SubmodulePrivate::preTerminate() - { - if (!repoEventsBlocked()) { - Events::self()->submoduleAboutToBeDeleted(repository(), pub()); - } - - RepoPrivate::preTerminate(); - } - - QString SubmodulePrivate::objectTypeName() const - { - return QStringLiteral("Submodule"); - } - - bool SubmodulePrivate::inherits(ObjTypes type) const - { - return type == SubmoduleObject || RepoPrivate::inherits(type); - } - -} diff --git a/Libs/libMacGitverCore/RepoMan/Tag.cpp b/Libs/libMacGitverCore/RepoMan/Tag.cpp deleted file mode 100644 index a530ef13..00000000 --- a/Libs/libMacGitverCore/RepoMan/Tag.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * MacGitver - * Copyright (C) 2012-2015 The MacGitver-Developers - * - * (C) Sascha Cunz - * (C) Cunz RaD Ltd. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License (Version 2) as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without - * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program; if - * not, see . - * - */ - -#include "Tag.hpp" -#include "Events.hpp" - -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/TagPrivate.hpp" - -namespace RM -{ - - using namespace Internal; - - Tag::Tag(Base* _parent, const Git::Reference& _ref) - : Ref(*new TagPrivate(this, _ref)) - { - RM_D(Tag); - d->linkToParent(_parent); - } - - //-- TagPrivate -------------------------------------------------------------------------------- - - TagPrivate::TagPrivate(Tag* _pub, const Git::Reference& _ref) - : RefPrivate(_pub, TagType, _ref) - { - } - - ObjTypes TagPrivate::objType() const - { - return TagObject; - } - - void TagPrivate::postCreation() - { - if (!repoEventsBlocked()) { - Events::self()->tagCreated(repository(), pub()); - } - - RefPrivate::postCreation(); - } - - void TagPrivate::preTerminate() - { - if (!repoEventsBlocked()) { - Events::self()->tagAboutToBeDeleted(repository(), pub()); - } - - RefPrivate::preTerminate(); - } - - void TagPrivate::dumpSelf(Internal::Dumper& dumper) const - { - dumper.addLine(QString(QStringLiteral("Tag 0x%1 - %2")) - .arg(quintptr(mPub),0,16) - .arg(mName)); - } - - QString TagPrivate::objectTypeName() const - { - return QStringLiteral("Tag"); - } - - bool TagPrivate::inherits(ObjTypes type) const - { - return type == TagObject || RefPrivate::inherits(type); - } - -} diff --git a/Libs/libMacGitverCore/Widgets/RepoStateWidget.cpp b/Libs/libMacGitverCore/Widgets/RepoStateWidget.cpp index 4338faec..c0d4f884 100644 --- a/Libs/libMacGitverCore/Widgets/RepoStateWidget.cpp +++ b/Libs/libMacGitverCore/Widgets/RepoStateWidget.cpp @@ -25,15 +25,15 @@ #include "libHeavenIcons/IconRef.hpp" #include "libHeavenIcons/Icon.hpp" -#include "RepoMan/Ref.hpp" -#include "RepoMan/RepoMan.hpp" -#include "RepoMan/Repo.hpp" +#include "libRepoMan/Frontend/Reference.hpp" +#include "libRepoMan/Frontend/Repo.hpp" + +#include "libRepoMan/RepoMan.hpp" #include "RepoStateWidget.hpp" RepoStateWidget::RepoStateWidget() { - repo = NULL; setupUi(); RM::RepoMan& rm = RM::RepoMan::instance(); @@ -48,20 +48,18 @@ RepoStateWidget::RepoStateWidget() this, &RepoStateWidget::repositoryDeactivated); } -void RepoStateWidget::repositoryActivated(RM::Repo* info) +void RepoStateWidget::repositoryActivated(const RM::Frontend::Repo& repo) { - if( repo != info ) - { - repo = info; + if (mRepo != repo) { + mRepo = repo; setRepoState(); } } -void RepoStateWidget::repositoryDeactivated(RM::Repo* info) +void RepoStateWidget::repositoryDeactivated(const RM::Frontend::Repo& repo) { - if( repo == info ) - { - repo = NULL; + if (mRepo == repo) { + mRepo = RM::Frontend::Repo(); setRepoState(); } } @@ -70,22 +68,25 @@ void RepoStateWidget::setRepoState() { txtState->hide(); - txtRepo->setText( repo ? repo->displayAlias() : QString() ); - onUpdateHEAD( repo, NULL ); + txtRepo->setText(mRepo ? mRepo.displayAlias() : QString()); + onUpdateHEAD(RM::Frontend::Reference()); } -void RepoStateWidget::onUpdateHEAD(RM::Repo* ownerRepo, RM::Ref* ref) +void RepoStateWidget::onUpdateHEAD( + const RM::Frontend::Reference& ref) { - if ( ownerRepo != repo ) { + RM::Frontend::Repo repo = ref.repository(); + + if (repo != mRepo) { return; } - if ( ref && ref->name() != QStringLiteral("HEAD") ) { + if (ref && ref.name() != QStringLiteral("HEAD")) { return; } // TODO: implement a HTML formatter to highlight HEAD - txtBranch->setText( repo ? repo->branchDisplay() : QString() ); + txtBranch->setText(repo ? repo.branchDisplay() : QString()); } static inline QLabel* pixmapLabel(const char* name) diff --git a/Libs/libMacGitverCore/Widgets/RepoStateWidget.hpp b/Libs/libMacGitverCore/Widgets/RepoStateWidget.hpp index 2fa038c0..773f3ad3 100644 --- a/Libs/libMacGitverCore/Widgets/RepoStateWidget.hpp +++ b/Libs/libMacGitverCore/Widgets/RepoStateWidget.hpp @@ -19,16 +19,12 @@ #pragma once +#include "libRepoMan/Frontend/Repo.hpp" + class QLabel; #include -namespace RM -{ - class Ref; - class Repo; -} - class RepoStateWidget : public QWidget { Q_OBJECT @@ -36,19 +32,19 @@ class RepoStateWidget : public QWidget RepoStateWidget(); private slots: - void repositoryActivated(RM::Repo* info); - void repositoryDeactivated(RM::Repo* info); + void repositoryActivated(const RM::Frontend::Repo& repo); + void repositoryDeactivated(const RM::Frontend::Repo& repo); private: void setupUi(); void setRepoState(); public slots: - void onUpdateHEAD(RM::Repo* ownerRepo, RM::Ref* ref); + void onUpdateHEAD(const RM::Frontend::Reference& ref); private: - RM::Repo* repo; - QLabel* txtRepo; - QLabel* txtState; - QLabel* txtBranch; + RM::Frontend::Repo mRepo; + QLabel* txtRepo; + QLabel* txtState; + QLabel* txtBranch; }; diff --git a/Libs/libRepoMan/Backend/AbstractService.cpp b/Libs/libRepoMan/Backend/AbstractService.cpp new file mode 100644 index 00000000..8d8e996c --- /dev/null +++ b/Libs/libRepoMan/Backend/AbstractService.cpp @@ -0,0 +1,61 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libLogger/Manager.hpp" +#include "libLogger/Event.hpp" + +#include "libRepoMan/Backend/AbstractService.hpp" +#include "libRepoMan/Backend/RepoMan.hpp" + +#include + +namespace RM { namespace Backend { + +AbstractService::AbstractService() +{ +} + +void AbstractService::execute() +{ + if (thread() != RepoMan::workerThread()) { + qDebug() << "Running a Service outside of the RepoMan Thread."; + Q_ASSERT(false); + return; + } + + emit started(); + + run(); + + emit finished(); +} + +void AbstractService::logGitError(const Git::Result& r, const char* msg) +{ + Log::Channel ch = RepoMan::instance().gitErrorChannel(); + Log::Template tpl = RepoMan::instance().gitErrorTemplate(); + Log::Event ev = Log::Event::create(tpl); + + ev.setParam(QStringLiteral("gwerror"), r.errorText()); + ev.setText(QString::fromUtf8(msg)); + + Log::Manager().addEvent(ch, ev); +} + +} } diff --git a/Libs/libMacGitverCore/RepoMan/Tag.hpp b/Libs/libRepoMan/Backend/AbstractService.hpp similarity index 63% rename from Libs/libMacGitverCore/RepoMan/Tag.hpp rename to Libs/libRepoMan/Backend/AbstractService.hpp index e40064d8..edf77744 100644 --- a/Libs/libMacGitverCore/RepoMan/Tag.hpp +++ b/Libs/libRepoMan/Backend/AbstractService.hpp @@ -19,29 +19,31 @@ #pragma once -#include "Ref.hpp" +#include "libGitWrap/Result.hpp" -namespace RM -{ +#include + +namespace RM { namespace Backend { - class MGV_CORE_API Tag : public Ref - { - public: - enum { StaticObjectType = TagObject }; - typedef QVector< Tag* > List; - typedef QSet< Tag* > Set; +class AbstractService + : public QObject +{ + Q_OBJECT +public: + AbstractService(); - public: - Tag(Base* _parent, const Git::Reference& _ref); +signals: + void started(); + void finished(); - public: +public: + void execute(); - private: - ObjTypes objType() const; - void preTerminate(); - void dumpSelf(Internal::Dumper& dumper) const; +protected: + virtual void run() = 0; - private: - }; +protected: + void logGitError(const Git::Result& r, const char* msg = nullptr); +}; -} +} } diff --git a/Libs/libRepoMan/Backend/RepoLocker.hpp b/Libs/libRepoMan/Backend/RepoLocker.hpp new file mode 100644 index 00000000..72438e92 --- /dev/null +++ b/Libs/libRepoMan/Backend/RepoLocker.hpp @@ -0,0 +1,57 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Data/Repo.hpp" + +namespace RM +{ + + namespace Backend + { + + class RepoLocker + { + public: + RepoLocker() = delete; + RepoLocker(const RepoLocker&) = delete; + + inline RepoLocker(const Data::Repo::SPtr& p) + : d(p) + { + if (d) { + d->mutex().lock(); + } + } + + inline ~RepoLocker() + { + if (d) { + d->mutex().unlock(); + } + } + + private: + Data::Repo::SPtr d; + }; + + } + +} diff --git a/Libs/libRepoMan/Backend/RepoMan.cpp b/Libs/libRepoMan/Backend/RepoMan.cpp new file mode 100644 index 00000000..e10ab95a --- /dev/null +++ b/Libs/libRepoMan/Backend/RepoMan.cpp @@ -0,0 +1,84 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Backend/RepoMan.hpp" + +#include "libLogger/Manager.hpp" + +#include +#include + +namespace RM +{ + + namespace Backend + { + + static RepoMan* repoMan() + { + static QPointer< RepoMan > sInstance; + if (sInstance.isNull()) { + sInstance = new RepoMan; + } + return sInstance; + } + + RepoMan::RepoMan() + : mWorkerThread(new QThread) + { + moveToThread(mWorkerThread); + mWorkerThread->start(); + + setupLogging(); + } + + RepoMan& RepoMan::instance() + { + return *repoMan(); + } + + QThread* RepoMan::workerThread() + { + return repoMan()->mWorkerThread; + } + + void RepoMan::setupLogging() + { + mGitErrorChannel = Log::Channel::create(tr("Git Errors")); + + Log::Manager().addChannel(mGitErrorChannel); + + mGitErrorTemplate = Log::Template::create(tr("Git Errors")); + mGitErrorTemplate.setTransformation(tr("$$ caused a git error: $gwerror$")); + Log::Manager().addTemplate(mGitErrorTemplate); + } + + Log::Channel RepoMan::gitErrorChannel() const + { + return mGitErrorChannel; + } + + Log::Template RepoMan::gitErrorTemplate() const + { + return mGitErrorTemplate; + } + + } + +} diff --git a/Libs/libRepoMan/Backend/RepoMan.hpp b/Libs/libRepoMan/Backend/RepoMan.hpp new file mode 100644 index 00000000..8a6284b6 --- /dev/null +++ b/Libs/libRepoMan/Backend/RepoMan.hpp @@ -0,0 +1,67 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Data/Repo.hpp" + +#include "libLogger/Channel.hpp" +#include "libLogger/Template.hpp" + +#include +#include + +namespace RM +{ + + namespace Backend + { + + class RepoMan + : public QObject + { + Q_OBJECT + public: + RepoMan(); + + public: + static RepoMan& instance(); + static QThread* workerThread(); + + public: + Data::Repo::SPtr findRepo(const QString& workTreePath) const; + + public: + Log::Channel gitErrorChannel() const; + Log::Template gitErrorTemplate() const; + + private: + void setupLogging(); + + private: + QThread* mWorkerThread; + mutable QMutex mRepoMan; + Data::Repo::SList mRepos; + Log::Channel mGitErrorChannel; + Log::Template mGitErrorTemplate; + }; + + } + +} diff --git a/Libs/libRepoMan/Backend/ServiceRunner.cpp b/Libs/libRepoMan/Backend/ServiceRunner.cpp new file mode 100644 index 00000000..00bd096d --- /dev/null +++ b/Libs/libRepoMan/Backend/ServiceRunner.cpp @@ -0,0 +1,122 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Backend/ServiceRunner.hpp" +#include "libRepoMan/Backend/AbstractService.hpp" +#include "libRepoMan/Backend/RepoMan.hpp" + +#include +#include +#include +#include + +namespace RM { namespace Backend { + +typedef QQueue< QPointer > ServiceQueue; + +class ServiceRunner::Data +{ +public: + QMutex mMtx; + +public: + ServiceQueue& queueFor(RunnerPriority priority); + AbstractService* dequeueNext(); + +private: + ServiceQueue mLowQueue, mDefaultQueue, mUrgentQueue, mImmediateQueue; +}; + +ServiceQueue& ServiceRunner::Data::queueFor(RunnerPriority priority) +{ + switch (priority) { + case RunnerPriority::Low: return mLowQueue; + case RunnerPriority::Default: return mDefaultQueue; + case RunnerPriority::Urgent: return mUrgentQueue; + case RunnerPriority::Immediate: return mImmediateQueue; + default: Q_ASSERT(false); + } +} + +AbstractService* ServiceRunner::Data::dequeueNext() +{ + QMutexLocker _(&mMtx); + + if (!mImmediateQueue.empty()) { + return mImmediateQueue.dequeue(); + } + else if (!mUrgentQueue.empty()) { + return mUrgentQueue.dequeue(); + } + else if (!mDefaultQueue.empty()) { + return mDefaultQueue.dequeue(); + } + else if (!mLowQueue.empty()) { + return mLowQueue.dequeue(); + } + + return NULL; +} + +void ServiceRunner::processNext() +{ + AbstractService* next = d->dequeueNext(); + + if (next) { + next->execute(); + } +} + +ServiceRunner::ServiceRunner() + : d(new Data) +{ + connect(this, &ServiceRunner::processNextService, + this, &ServiceRunner::processNext, + Qt::QueuedConnection); +} + +ServiceRunner::~ServiceRunner() +{ + delete d; +} + +void ServiceRunner::enqueue(Backend::AbstractService* svc, RunnerPriority priority) +{ + QMutexLocker(&d->mMtx); + + ServiceQueue& queue(d->queueFor(priority)); + svc->moveToThread(Backend::RepoMan::workerThread()); + queue.enqueue(svc); + + emit processNextService(); +} + +ServiceRunner& ServiceRunner::instance() +{ + QPointer< ServiceRunner > sSelf; + + if (sSelf.isNull()) { + sSelf = new ServiceRunner; + sSelf->moveToThread(Backend::RepoMan::workerThread()); + } + + return *sSelf; +} + +} } diff --git a/Libs/libMacGitverCore/RepoMan/CollectionNode.hpp b/Libs/libRepoMan/Backend/ServiceRunner.hpp similarity index 52% rename from Libs/libMacGitverCore/RepoMan/CollectionNode.hpp rename to Libs/libRepoMan/Backend/ServiceRunner.hpp index b0ea932d..046f2eed 100644 --- a/Libs/libMacGitverCore/RepoMan/CollectionNode.hpp +++ b/Libs/libRepoMan/Backend/ServiceRunner.hpp @@ -19,34 +19,51 @@ #pragma once -#include +#include -#include "Base.hpp" +namespace RM { namespace Backend { -namespace RM +class AbstractService; + +enum class RunnerPriority +{ + Low, + Default, + Urgent, + Immediate, +}; + +class ServiceRunner + : public QObject { + Q_OBJECT +private: + ServiceRunner(); +public: + ~ServiceRunner(); - namespace Internal - { - class CollectionNodePrivate; - } +public: + static ServiceRunner& instance(); - class MGV_CORE_API CollectionNode : public Base - { - Q_DECLARE_TR_FUNCTIONS(RM_CollectionNode) +public: + void enqueue(Backend::AbstractService* svc, RunnerPriority priority); - public: - enum { StaticObjectType = CollectionNodeObject }; - typedef Internal::CollectionNodePrivate Private; - typedef QSet< CollectionNode* > Set; - typedef QVector< CollectionNode* > List; +signals: + void processNextService(); - public: - CollectionNode(CollectionTypes _ctype, Base* parent); +private: + void processNext(); - public: - CollectionTypes collectionType() const; - QString collectionTypeName() const; - }; +private: + class Data; + Data* d; +}; +static inline void perform( + Backend::AbstractService* svc, + RunnerPriority priority = RunnerPriority::Default) +{ + ServiceRunner::instance().enqueue(svc, priority); } + +} } diff --git a/Libs/libRepoMan/CMakeLists.txt b/Libs/libRepoMan/CMakeLists.txt new file mode 100644 index 00000000..f500985d --- /dev/null +++ b/Libs/libRepoMan/CMakeLists.txt @@ -0,0 +1,150 @@ + +PROJECT(REPOMAN) + +QT_PREPARE(Core Gui Widgets) + +INCLUDE_DIRECTORIES( BEFORE + ${REPOMAN_SOURCE_DIR} + ${REPOMAN_BINARY_DIR} +) + +SET( SRC_FILES + + RepoMan.cpp + + Events/Event.cpp + Events/EventData.cpp + Events/Manager.cpp + Events/Compat.cpp + + Frontend/Base.cpp + Frontend/Branch.cpp + Frontend/Namespace.cpp + Frontend/Reference.cpp + Frontend/RefLog.cpp + Frontend/RefTreeNode.cpp + Frontend/Remote.cpp + Frontend/Repo.cpp + Frontend/Submodule.cpp + Frontend/Tag.cpp + Frontend/Head.cpp + + Data/Base.cpp + Data/Branch.cpp + Data/Namespace.cpp + Data/Reference.cpp + Data/RefLog.cpp + Data/RefTreeNode.cpp + Data/Remote.cpp + Data/Repo.cpp + Data/Submodule.cpp + Data/Tag.cpp + Data/Head.cpp + + Private/Dumper.cpp + + Backend/AbstractService.cpp + Backend/ServiceRunner.cpp + Backend/RepoMan.cpp + + Services/OpenRepository.cpp + Services/RefreshRepository.cpp +) + +SET( PUB_HDR_FILES + + Core.hpp + RepoMan.hpp + + Events/Event.hpp + Events/Manager.hpp + Events/Compat.hpp + + Frontend/Base.hpp + Frontend/Reference.hpp + Frontend/Repo.hpp + Frontend/Remote.hpp + Frontend/Tag.hpp + Frontend/Branch.hpp + Frontend/RefLog.hpp + Frontend/Submodule.hpp + Frontend/RefTreeNode.hpp + Frontend/Namespace.hpp + Frontend/Head.hpp +) + +SET( PRI_HDR_FILES + + Private/Dumper.hpp + + Events/EventData.hpp + + Data/Base.hpp + Data/Branch.hpp + Data/Namespace.hpp + Data/Reference.hpp + Data/RefLog.hpp + Data/RefTreeNode.hpp + Data/Remote.hpp + Data/Repo.hpp + Data/RepoMan.hpp + Data/Submodule.hpp + Data/Tag.hpp + Data/Head.hpp + + Frontend/BaseInternal.hpp + + Backend/AbstractService.hpp + Backend/ServiceRunner.hpp + Backend/RepoMan.hpp + Backend/RepoLocker.hpp + + Services/OpenRepository.hpp + Services/RefreshRepository.hpp +) + +SET( HID_FILES + + Private/RepoManActions.hid +) + +SET( HDR_FILES ${PRI_HDR_FILES} ${PUB_HDR_FILES} ) + +QT_MOC( MOC_FILES ${HDR_FILES} ) +HIC( HIC_FILES ${HID_FILES} ) + +ADD_QT_LIBRARY( + RepoMan SHARED + + ${SRC_FILES} + ${HDR_FILES} + ${MOC_FILES} + ${HIC_FILES} ${HID_FILES} +) + +TARGET_LINK_LIBRARIES( + RepoMan + + LINK_PUBLIC + HeavenActions + HeavenIcons + BlueSky + + LINK_PRIVATE + Logger + GitWrap +) + +IF(UNIX AND NOT APPLE) + SET_TARGET_PROPERTIES( + RepoMan + PROPERTIES INSTALL_RPATH + "\$ORIGIN" + ) +ENDIF() + +RAD_DEFINE_VERSION(REPOMAN 0 0 1) +RAD_SET_TARGET_VERSION( RepoMan REPOMAN ) +RAD_INSTALL_LIBRARY( RepoMan RepoMan ) +RAD_INSTALL_HEADERS( libRepoMan ${PUB_HDR_FILES} ) +RAD_SPLIT_SOURCE_TREE( RepoMan ) diff --git a/Libs/libMacGitverCore/RepoMan/Ref.hpp b/Libs/libRepoMan/Core.hpp similarity index 52% rename from Libs/libMacGitverCore/RepoMan/Ref.hpp rename to Libs/libRepoMan/Core.hpp index ada176ce..36f5bbf4 100644 --- a/Libs/libMacGitverCore/RepoMan/Ref.hpp +++ b/Libs/libRepoMan/Core.hpp @@ -19,47 +19,57 @@ #pragma once -#include "libGitWrap/ObjectId.hpp" +#include +#include +#include +#include -#include "Base.hpp" +#include + +#ifdef RepoMan_EXPORTS +# define REPOMAN_API Q_DECL_EXPORT +#else +# define REPOMAN_API Q_DECL_IMPORT +#endif + +namespace Heaven { + + class Menu; + class IconRef; + +} namespace RM { - namespace Internal + enum class ObjTypes { - class RefPrivate; - } + Invalid, - enum RefTypes - { - BranchType, - TagType + Namespace, + Repo, + Remote, + Submodule, + Head, + Branch, + Reference, + RefTreeNode, + Tag, + RefLog }; - class MGV_CORE_API Ref : public Base + namespace Frontend { - public: - enum { StaticObjectType = RefObject }; - - typedef QSet< Ref* > Set; - typedef QList< Ref* > List; - - protected: - Ref(Internal::RefPrivate& data); - - public: - Ref(Base* parent, RefTypes type, const Git::Reference& ref); - - GW_DEPRECATED - Git::Reference load(Git::Result& r); - - public: - RefTypes type() const; - QString name() const; - QString fullName() const; - Git::ObjectId id() const; - QString displaySha1() const; - }; + class Base; + class Repo; + class RefTreeNode; + class Namespace; + class Reference; + class Remote; + class RefLog; + class Submodule; + class Tag; + class Branch; + } } diff --git a/Libs/libRepoMan/Data/Base.cpp b/Libs/libRepoMan/Data/Base.cpp new file mode 100644 index 00000000..05443c3e --- /dev/null +++ b/Libs/libRepoMan/Data/Base.cpp @@ -0,0 +1,356 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Data/Base.hpp" + +#include "libRepoMan/Events/Manager.hpp" +#include "libRepoMan/Events/EventData.hpp" + +#include "libRepoMan/Frontend/Repo.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libHeavenIcons/IconRef.hpp" + +namespace RM +{ + + namespace Data + { + + Base::Base() + : mRepo() + , mParent() + { + } + + Base::~Base() + { + } + + /** + * @internal + * @brief Recursively dump this object into a dumper + * + * All children will be dumped recursively. + * + * @param[in] dumper The dumper to output to + * + */ + void Base::dumpRecursive(Internal::Dumper& dumper) const + { + dumpSelf(dumper); + + dumper.indent(); + dumpChildren(dumper); + dumper.dedent(); + } + + void Base::dumpChildren(Internal::Dumper& dumper) const + { + Q_UNUSED(dumper); + /* Nothinng to do for base class */ + } + + QString Base::displayName() const + { + return QStringLiteral(""); + } + + void Base::emitEvent(EventType type) + { + Event ev(Internal::EventData::create(type, this)); + EventManager::self().sendEvent(ev); + } + + #if 0 // ###REPOMAN + /** + * @brief Refresh this object + * + * Refreshes this object and all its children. First calls to refreshSelf() expecting it to + * update this object and send out events. If refreshSelf() returns `false`, this object is + * removed from the tree. In this case all children should already have been removed from the + * tree. + * + * If refreshSelf() returned `true`, preRefreshChildren() is called. It should remove children + * that are no longer part of the tree. After that for each child, refresh() is called + * recursively. Finally, postRefreshChildren() is invoked, which should search for new objects + * and link them into the tree. + * + * If preRefreshChildren() is implemented correctly on all objects, refreshSelf() should + * probably never have to return `false`. + * + */ + void Base::refresh() + { + if (!refreshSelf()) { + // If refresh self returned false, we are no longer valid and will now destroy + // ourselves. We just terminateObject(). + terminateObject(); + return; + } + + postRefresh(); + preRefreshChildren(); + + foreach(Base* child, mChildren) { + child->mData->refresh(); + } + + postRefreshChildren(); + + if (refreshCheckDispensable()) { + terminateObject(); + } + } + + void Base::postRefresh() + { + } + + /** + * @brief Check if this object is dispensable + * + * @return @c true to dispense this object + * + * During the refresh cycle, this is the last method called for each object. If it returns + * @c true, the object will be terminated. + * + * This can be used for container objects that shall actually get dispensed once they have no + * more children (i.e. RefTreeNode). + * + */ + bool Base::refreshCheckDispensable() + { + return false; + } + + /** + * @brief First step in refreshing the children + * + * This method is called directly after the object refreshed itself (refreshSelf()) but before + * any of its children are refreshed. + * + * It shall be used to figure out which children do no longer exist. + * + * The base implementation simply does nothing. + * + */ + void Base::preRefreshChildren() + { + } + + /** + * @brief Last step in refreshing the children + * + * This method is called as last step in the refreshing process. It shall be used to find + * objects and add them to the tree. + * + * The base implementation simply does nothing. + * + */ + void Base::postRefreshChildren() + { + } + + /** + * @brief Terminates the lifetime of this object + * + * This method MUST be used to destroy an object. Don't just delete an repoman object. + * + * 1. For all children, terminateObject() gets invoked. + * 2. preTerminate() is called, whose objective is to send an event if required. + * 3. the object is unlinkedFromParent() + * 4. finally it deletes itself. Deleting is not defered; the object is gone immediately. + * + */ + void Base::terminateObject() + { + foreach (Base* child, mChildren) { + child->mData->terminateObject(); + } + + preTerminate(); + unlinkFromParent(); + delete this; + } + + /** + * @brief Are Events blocked for the repository this object belongs to? + * + * @return `true` if any events for this repository shall be suppressed. `false` in normal + * operation. + * + * During the construction of a repository and its initial seeding with objects, no events will + * be send to any listeners. This method must be used to query whether we're currently in that + * phase or not. + * + */ + bool Base::repoEventsBlocked() + { + Q_ASSERT(mRepo); + return mRepo->isInitializing(); + } + + /** + * @brief Pre-Termination call + * + * This method is called prior to doing the actual object termination. Its objective is to send + * out any required events to listeners, unless this repository is still initializing. + * + * The base implementation will send out a objectAboutToDelete() event. + */ + void Base::preTerminate() + { + if (!repoEventsBlocked()) { + Events::self()->objectAboutToBeDeleted(repository(), mPub); + } + } + + /** + * @brief Post-Construction call + * + * This method is called just before the last constructor is finished. The call actually will + * come from linkToParent(). + * + * The purpose of this method is to send a creation event. The base implementation will send a + * objectCreated() event. + * + * Note that no events should be sent out, if repoEventsBlocked() returns `true`. + * + */ + void Base::postCreation() + { + if (!repoEventsBlocked()) { + Events::self()->objectCreated(repository(), mPub); + } + } + #endif + + #if 0 // ###REPOMAN move to RefreshService + /** + * @brief Find the parent for a Ref. + * + * @param[in] scopes List of scopes to search for or to create. + * + * @param[in] create If `true` and @a path is not empty, a reference tree node will be + * created, if none is found. If `false`, `nullptr` will be returned. + * + * @return If @a scopes is empty, `this` is returned. Otherwise findRefTreeNode() is called + * to either find or create a RefTreeNode, which will be returned. + */ + Base* Base::findRefParent(const QStringList& scopes, bool create) + { + if (scopes.isEmpty()) { + return mPub; + } + return findRefTreeNode(scopes, create); + } + + /** + * @brief Search for or create a ref tree node + * + * Searches for a RefTreeNode for path. + * + * @param[in] scopes List of scopes to search for or to create. Must not be empty. + * + * @param[in] create If `true` and a part of the tree node cannot be found, it will be + * created. If `false`, `nullptr` will be returned in that case. + * + * @return If @a create is `true`, a valid RefTreeNode is returned. If @a create is + * `false`, `nullptr` will be returned in case the path cannot be found. + */ + RefTreeNode* Base::findRefTreeNode(const QStringList &scopes, bool create) + { + if (scopes.isEmpty()) { + return nullptr; + } + + Base* current = mPub; + + foreach (QString scope, scopes) { + RefTreeNode::List nodes = current->childObjects(); + RefTreeNode* next = nullptr; + + foreach(RefTreeNode* child, nodes) { + if (child->name() == scope) { + next = child; + break; + } + } + + if (!next) { + if (create) { + // Note: We don't need to roll this back. Either we go all the way or nowhere. + next = new RefTreeNode(current, scope); + } + else { + return nullptr; + } + } + + current = next; + } + + return static_cast< RefTreeNode* >(current); + } + + CollectionNode* Base::getOrCreateCollection(CollectionTypes ctype) + { + CollectionNode* cn; + + foreach (cn, mPub->childObjects()) { + if (cn->collectionType() == ctype) { + return cn; + } + } + + return new CollectionNode(ctype, mPub); + } + #endif + + Heaven::IconRef Base::icon(bool small) const + { + QString size = small ? QStringLiteral("@16") : QStringLiteral("@24"); + return Heaven::IconRef::fromString(QChar(L'#') % objectTypeName() % size); + } + + bool Base::inherits(ObjTypes type) const + { + return false; + } + + Base::WList Base::children() const + { + return Base::WList(); + } + + std::weak_ptr Base::repository() const + { + return mRepo; + } + + std::shared_ptr Base::parent() const + { + return mParent.lock(); + } + + } + +} diff --git a/Libs/libRepoMan/Data/Base.hpp b/Libs/libRepoMan/Data/Base.hpp new file mode 100644 index 00000000..d28974d2 --- /dev/null +++ b/Libs/libRepoMan/Data/Base.hpp @@ -0,0 +1,148 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Events/Event.hpp" + +#include +#include +#include + +#ifdef _MSVC +#define const_or_constexpr const +#else +#define const_or_constexpr constexpr +#endif + +namespace RM +{ + + namespace Internal + { + class Dumper; + } + + namespace Frontend + { + class Base; + } + + namespace Data + { + + class Repo; + + class Base + : public std::enable_shared_from_this + { + public: + using FrontendT = Frontend::Base; + using SPtr = std::shared_ptr; + using WPtr = std::weak_ptr; + using SList = std::vector; + using WList = std::vector; + + private: + Base(const Base&) = delete; + Base& operator=(const Base&) = delete; + + protected: + Base(); + + public: + virtual ~Base(); + + public: + void dumpRecursive(Internal::Dumper& dumper) const; + + std::weak_ptr repository() const; + SPtr parent() const; + + public: + SPtr getPtr() { return shared_from_this(); } + + public: + virtual QString displayName() const; + virtual QString objectTypeName() const = 0; + virtual Heaven::IconRef icon(bool small) const; + virtual bool inherits(ObjTypes type) const; + virtual ObjTypes objType() const = 0; + virtual void dumpSelf(Internal::Dumper& dumper) const = 0; + void dumpChildren(Internal::Dumper& dumper) const; + + virtual WList children() const; + + template + std::shared_ptr as() const; + + template + std::shared_ptr as(); + + protected: + void emitEvent(EventType type); + + private: + std::weak_ptr mRepo; + std::weak_ptr mParent; + }; + + template + inline std::shared_ptr Base::as() const + { + if (inherits(T::StaticObjectType)) { + return std::static_pointer_cast(shared_from_this()); + } + return std::shared_ptr(); + } + + template + inline std::shared_ptr Base::as() + { + if (inherits(T::StaticObjectType)) { + return std::static_pointer_cast(shared_from_this()); + } + return std::shared_ptr(); + } + + template + typename T::SList sharedFromWeakList(const typename T::WList& wlist) + { + typename T::SList slist; + for (const typename T::WPtr& wptr : wlist) { + if (auto sptr = wptr.lock()) { + slist.push_back(sptr); + } + } + return slist; + } + + template + typename T::WList weakFromSharedList(const typename T::SList& slist) + { + typename T::WList wlist; + for (const typename T::SPtr& sptr : slist) { + wlist.push_back(sptr); + } + return wlist; + } + + } + +} diff --git a/Libs/libRepoMan/Data/Branch.cpp b/Libs/libRepoMan/Data/Branch.cpp new file mode 100644 index 00000000..bbf93812 --- /dev/null +++ b/Libs/libRepoMan/Data/Branch.cpp @@ -0,0 +1,97 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Events.hpp" + +#include "libRepoMan/Data/Branch.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +namespace RM +{ + + namespace Data + { + + Branch::Branch(Frontend::Branch* pub, const Git::Reference& ref) + : Reference(pub, BranchType, ref) + , mHasUpstream(false) + , mAheadCount(0) + , mBehindCount(0) + { + } + + ObjTypes Branch::objType() const + { + return ObjTypes::Branch; + } + + #if 0 // ###DEAD + void Branch::postCreation() + { + jif (!repoEventsBlocked()) { + Events::self()->branchCreated(repository(), pub()); + } + + RefPrivate::postCreation(); + } + + void Branch::preTerminate() + { + if (!repoEventsBlocked()) { + Events::self()->branchAboutToBeDeleted(repository(), pub()); + } + + RefPrivate::preTerminate(); + } + + void Branch::dumpSelf(Internal::Dumper& dumper) const + { + dumper.addLine(QString(QStringLiteral("Branch 0x%1 - %2")) + .arg(quintptr(mPub),0,16) + .arg(mName)); + } + + QString Branch::objectTypeName() const + { + return QStringLiteral("Branch"); + } + + void Branch::emitMoved() + { + if (!repoEventsBlocked()) { + Events::self()->refMoved(mRepo, pub()); + Events::self()->branchMoved(mRepo, pub()); + } + } + #endif + + bool Branch::refreshDetails(const Git::Reference& ref) + { + return Reference::refreshDetails(ref); + } + + bool Branch::inherits(ObjTypes type) const + { + return type == ObjTypes::Branch || Reference::inherits(type); + } + + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/Private/BranchPrivate.hpp b/Libs/libRepoMan/Data/Branch.hpp similarity index 76% rename from Libs/libMacGitverCore/RepoMan/Private/BranchPrivate.hpp rename to Libs/libRepoMan/Data/Branch.hpp index ad7f54bb..23cdd606 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/BranchPrivate.hpp +++ b/Libs/libRepoMan/Data/Branch.hpp @@ -19,20 +19,23 @@ #pragma once -#include "RepoMan/Private/RefPrivate.hpp" +#include "libRepoMan/Data/Reference.hpp" -#include "RepoMan/Branch.hpp" +#include "libRepoMan/Frontend/Branch.hpp" namespace RM { - namespace Internal + namespace Data { - class BranchPrivate : public RefPrivate + class Branch + : public Reference { public: - BranchPrivate(Branch* pub, const Git::Reference& ref); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Branch; + public: + Branch(Frontend::Branch* pub, const Git::Reference& ref); public: ObjTypes objType() const; @@ -40,7 +43,7 @@ namespace RM void preTerminate(); bool refreshDetails(const Git::Reference& ref); void emitMoved(); - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; diff --git a/Libs/libMacGitverCore/RepoMan/Head.cpp b/Libs/libRepoMan/Data/Head.cpp similarity index 50% rename from Libs/libMacGitverCore/RepoMan/Head.cpp rename to Libs/libRepoMan/Data/Head.cpp index 0a312cda..cf1f391d 100644 --- a/Libs/libMacGitverCore/RepoMan/Head.cpp +++ b/Libs/libRepoMan/Data/Head.cpp @@ -17,13 +17,11 @@ * */ -#include "Head.hpp" -#include "Events.hpp" +#include "libRepoMan/Events.hpp" -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/HeadPrivate.hpp" -#include "RepoMan/Branch.hpp" -#include "RepoMan/Repo.hpp" +#include "libRepoMan/Data/Head.hpp" + +#include "libRepoMan/Private/Dumper.hpp" #include "libGitWrap/Repository.hpp" #include "libGitWrap/BranchRef.hpp" @@ -31,13 +29,12 @@ namespace RM { - namespace Internal + namespace Data { - // -- HeadPrivate ----------------------------------------------------------------------- >8 - - HeadPrivate::HeadPrivate(Head* _pub, const Git::Repository& repo) - : BasePrivate(_pub) + #if 0 + Head::Head(Frontend::Head* _pub, const Git::Repository& repo) + : Base(_pub) , symbolicName() , isDetached(repo.isHeadDetached()) , isUnborn(repo.isHeadUnborn()) @@ -52,19 +49,19 @@ namespace RM } } - ObjTypes HeadPrivate::objType() const + ObjTypes Head::objType() const { - return HeadObject; + return ObjTypes::Head; } - void HeadPrivate::dumpSelf(Internal::Dumper& dumper) const + void Head::dumpSelf(Internal::Dumper& dumper) const { dumper.addLine(QString(QStringLiteral("Head 0x%1 - %2")) .arg(quintptr(mPub),0,16) .arg(symbolicName)); } - bool HeadPrivate::refreshSelf() + bool Head::refreshSelf() { Git::Repository repo = repository()->gitLoadedRepo(); Git::Result r; @@ -80,70 +77,23 @@ namespace RM } return true; } + #endif - QString HeadPrivate::displayName() const + QString Head::displayName() const { - return symbolicName; + return mSymbolicName; } - QString HeadPrivate::objectTypeName() const + QString Head::objectTypeName() const { return QStringLiteral("Head"); } - bool HeadPrivate::inherits(ObjTypes type) const + bool Head::inherits(ObjTypes type) const { - return type == HeadObject || BasePrivate::inherits(type); - } - - } - - // -- Head ---------------------------------------------------------------------------------- >8 - - Head::Head(const Git::Repository& ref, Base* parent) - : Base(*new Internal::HeadPrivate(this, ref)) - { - RM_D(Head); - d->linkToParent(parent); - } - - QString Head::symbolicName() const - { - RM_CD(Head); - if (d->isDetached) { - return QString(); - } - return d->symbolicName; - } - - bool Head::isDetached() const - { - RM_CD(Head); - return d->isDetached; - } - - bool Head::isUnborn() const - { - RM_CD(Head); - return d->isUnborn; - } - - Git::ObjectId Head::detachedId() const - { - RM_CD(Head); - return d->detachedId; - } - - bool Head::is(const Branch* ref) const - { - RM_CD(Head); - - if (d->isDetached || d->isUnborn) { - /* If it's unborn, it cannot match an existing branch anyway */ - return false; + return type == ObjTypes::Head || Base::inherits(type); } - return ref && d->symbolicName == ref->fullName(); } } diff --git a/Libs/libRepoMan/Data/Head.hpp b/Libs/libRepoMan/Data/Head.hpp new file mode 100644 index 00000000..0e31ae13 --- /dev/null +++ b/Libs/libRepoMan/Data/Head.hpp @@ -0,0 +1,84 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Data/Base.hpp" + +#include "libRepoMan/Frontend/Head.hpp" + +namespace RM +{ + + namespace Data + { + + class Head + : public Base + { + public: + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Head; + + public: + Head(Frontend::Head* pub, const Git::Repository& ref); + + public: + ObjTypes objType() const; + bool refreshSelf(); + QString displayName() const; + void dumpSelf(Internal::Dumper& dumper) const; + QString objectTypeName() const; + bool inherits(ObjTypes type) const; + + public: + bool isDetached() const; + bool isUnborn() const; + Git::ObjectId detachedId() const; + QString symbolicName() const; + + private: + QString mSymbolicName; + Git::ObjectId mDetachedId; + bool mIsDetached : 1; + bool mIsUnborn : 1; + }; + + inline bool Head::isDetached() const + { + return mIsDetached; + } + + inline bool Head::isUnborn() const + { + return mIsUnborn; + } + + inline Git::ObjectId Head::detachedId() const + { + return mDetachedId; + } + + inline QString Head::symbolicName() const + { + return mSymbolicName; + } + + } + +} diff --git a/Libs/libRepoMan/Data/Namespace.cpp b/Libs/libRepoMan/Data/Namespace.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Libs/libMacGitverCore/RepoMan/Private/CollectionNodePrivate.hpp b/Libs/libRepoMan/Data/Namespace.hpp similarity index 73% rename from Libs/libMacGitverCore/RepoMan/Private/CollectionNodePrivate.hpp rename to Libs/libRepoMan/Data/Namespace.hpp index ca4fd49d..76c6804f 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/CollectionNodePrivate.hpp +++ b/Libs/libRepoMan/Data/Namespace.hpp @@ -19,20 +19,24 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Base.hpp" -#include "RepoMan/CollectionNode.hpp" +#include "libRepoMan/Frontend/Namespace.hpp" namespace RM { - namespace Internal + namespace Data { - class CollectionNodePrivate : public BasePrivate + class Namespace + : public Base { public: - CollectionNodePrivate(CollectionNode* _pub, CollectionTypes _ctype); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Namespace; + + public: + Namespace(Namespace* _pub, const QString& _name); public: ObjTypes objType() const; @@ -40,13 +44,12 @@ namespace RM void postCreation(); void preTerminate(); QString displayName() const; - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; - Heaven::IconRef icon(bool small) const; bool inherits(ObjTypes type) const; public: - CollectionTypes ctype; + QString name; }; } diff --git a/Libs/libRepoMan/Data/RefLog.cpp b/Libs/libRepoMan/Data/RefLog.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Libs/libMacGitverCore/RepoMan/Private/NamespacePrivate.hpp b/Libs/libRepoMan/Data/RefLog.hpp similarity index 76% rename from Libs/libMacGitverCore/RepoMan/Private/NamespacePrivate.hpp rename to Libs/libRepoMan/Data/RefLog.hpp index 8af0ae3b..1f697948 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/NamespacePrivate.hpp +++ b/Libs/libRepoMan/Data/RefLog.hpp @@ -19,33 +19,33 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Base.hpp" -#include "RepoMan/Namespace.hpp" +#include "libRepoMan/Frontend/RefLog.hpp" namespace RM { - namespace Internal + namespace Data { - class NamespacePrivate : public BasePrivate + class RefLog + : public Base { public: - NamespacePrivate(Namespace* _pub, const QString& _name); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::RefLog; + + public: + RefLog(RefLog* _pub); public: ObjTypes objType() const; bool refreshSelf(); void postCreation(); void preTerminate(); - QString displayName() const; - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; - - public: - QString name; }; } diff --git a/Libs/libRepoMan/Data/RefTreeNode.cpp b/Libs/libRepoMan/Data/RefTreeNode.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Libs/libMacGitverCore/RepoMan/Private/RefTreeNodePrivate.hpp b/Libs/libRepoMan/Data/RefTreeNode.hpp similarity index 75% rename from Libs/libMacGitverCore/RepoMan/Private/RefTreeNodePrivate.hpp rename to Libs/libRepoMan/Data/RefTreeNode.hpp index fa60c315..ff6989b2 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/RefTreeNodePrivate.hpp +++ b/Libs/libRepoMan/Data/RefTreeNode.hpp @@ -19,20 +19,24 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Base.hpp" -#include "RepoMan/RefTreeNode.hpp" +#include "libRepoMan/Frontend/RefTreeNode.hpp" namespace RM { - namespace Internal + namespace Data { - class RefTreeNodePrivate : public BasePrivate + class RefTreeNode + : public Base { public: - RefTreeNodePrivate(RefTreeNode* _pub, const QString& _name); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::RefTreeNode; + + public: + RefTreeNode(RefTreeNode* _pub, const QString& _name); public: ObjTypes objType() const; @@ -41,7 +45,7 @@ namespace RM void preTerminate(); bool refreshCheckDispensable(); QString displayName() const; - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; diff --git a/Libs/libRepoMan/Data/Reference.cpp b/Libs/libRepoMan/Data/Reference.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Libs/libMacGitverCore/RepoMan/Private/RefPrivate.hpp b/Libs/libRepoMan/Data/Reference.hpp similarity index 75% rename from Libs/libMacGitverCore/RepoMan/Private/RefPrivate.hpp rename to Libs/libRepoMan/Data/Reference.hpp index 377b79d5..e07c5ef6 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/RefPrivate.hpp +++ b/Libs/libRepoMan/Data/Reference.hpp @@ -19,20 +19,24 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Base.hpp" -#include "RepoMan/Ref.hpp" +#include "libRepoMan/Frontend/Reference.hpp" namespace RM { - namespace Internal + namespace Data { - class RefPrivate : public BasePrivate + class Reference + : public Base { public: - RefPrivate(Ref* pub, RefTypes type, const Git::Reference& ref); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Reference; + + public: + Reference(Frontend::Reference* pub, RefTypes type, const Git::Reference& ref); public: ObjTypes objType() const; @@ -42,7 +46,7 @@ namespace RM void preTerminate(); virtual bool refreshDetails(const Git::Reference& ref); virtual void emitMoved(); - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; @@ -53,6 +57,9 @@ namespace RM Git::ObjectId mId; }; + GW_DEPRECATED + typedef Reference Ref; + } } diff --git a/Libs/libRepoMan/Data/Remote.cpp b/Libs/libRepoMan/Data/Remote.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Libs/libMacGitverCore/RepoMan/Private/RemotePrivate.hpp b/Libs/libRepoMan/Data/Remote.hpp similarity index 76% rename from Libs/libMacGitverCore/RepoMan/Private/RemotePrivate.hpp rename to Libs/libRepoMan/Data/Remote.hpp index 0c8b2fec..3d8f8b44 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/RemotePrivate.hpp +++ b/Libs/libRepoMan/Data/Remote.hpp @@ -19,22 +19,26 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Base.hpp" -#include "RepoMan/Remote.hpp" +#include "libRepoMan/Frontend/Remote.hpp" namespace RM { - class Head; - - namespace Internal + namespace Data { - class RemotePrivate : public BasePrivate + class Head; + + class Remote + : public Base { public: - RemotePrivate(Remote* _pub, const Git::Remote& _obj); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Remote; + + public: + Remote(Remote* _pub, const Git::Remote& _obj); public: ObjTypes objType() const; @@ -42,7 +46,7 @@ namespace RM void postCreation(); void preTerminate(); QString displayName() const; - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; diff --git a/Libs/libRepoMan/Data/Repo.cpp b/Libs/libRepoMan/Data/Repo.cpp new file mode 100644 index 00000000..60d90bed --- /dev/null +++ b/Libs/libRepoMan/Data/Repo.cpp @@ -0,0 +1,90 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Data/Repo.hpp" + +namespace RM +{ + + namespace Data + { + + Repo::Repo(const Git::Repository& repo) + : mHead(nullptr) + , mRepo(repo) + { + } + + Repo::~Repo() + { + } + + Git::Repository Repo::gitRepo(bool doLoad) + { + if (!mRepo && doLoad) { + Q_ASSERT(false); // ###REPOMAN - Not sure if we still want to support this... + } + + return mRepo; + } + + Repo::SPtr Repo::repoByPath(const QString& basePath, bool searchSubmodules) + { + for (const Repo::SPtr& subRepo : mSubmodules) { + if (subRepo->path() == basePath) { + return subRepo; + } + + if (searchSubmodules) { + Repo::SPtr found = subRepo->repoByPath(basePath, true); + if (found) { + return found; + } + } + } + + return Repo::SPtr(); + } + + ObjTypes Repo::objType() const + { + return ObjTypes::Repo; + } + + QString Repo::displayName() const + { + return QStringLiteral("Repo"); + } + + void Repo::dumpSelf(Internal::Dumper& dumper) const + { + } + + QString Repo::objectTypeName() const + { + } + + bool Repo::inherits(ObjTypes type) const + { + return type == ObjTypes::Repo || Base::inherits(type); + } + + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/Private/RepoPrivate.hpp b/Libs/libRepoMan/Data/Repo.hpp similarity index 57% rename from Libs/libMacGitverCore/RepoMan/Private/RepoPrivate.hpp rename to Libs/libRepoMan/Data/Repo.hpp index 2b16deab..9d240545 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/RepoPrivate.hpp +++ b/Libs/libRepoMan/Data/Repo.hpp @@ -19,71 +19,102 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Base.hpp" -#include "RepoMan/Repo.hpp" +#include "libRepoMan/Frontend/Repo.hpp" + +#include + +class QTimer; namespace RM { - class Head; - - namespace Internal + namespace Data { - class RepoPrivate : public BasePrivate + class Reference; + class Remote; + class Namespace; + class Head; + + class Repo + : public Base { public: - RepoPrivate(Repo* pub, const Git::Repository& repo); - ~RepoPrivate(); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Repo; + + public: + using FrontendT = Frontend::Repo; + using SPtr = std::shared_ptr; + using WPtr = std::weak_ptr; + using SList = std::vector; + using WList = std::vector; + + public: + Repo(const Git::Repository& repo); + ~Repo(); public: ObjTypes objType() const; - bool refreshSelf(); - void preTerminate(); - void postRefreshChildren(); QString displayName() const; - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; - Repo* searchRepository(); public: - Ref* findReference( const Git::Reference& ref, bool create = false); - Ref* findReference( const QString& fqrn, bool create = false); - Remote* findRemote( const Git::Remote& remote, bool create = false); + Reference* findReference( const QString& fqrn, bool create = false); + Remote* findRemote( const QString& remoteName, bool create = false); + Namespace* findNamespace( const QStringList& _namespaces, bool create = false); Namespace* findNamespace( const QString& nsFullName, bool create = false); private: - Ref* findReference(Git::RefName &rn, Git::Reference ref, bool create); + GW_DEPRECATED + Reference* findReference(Git::RefName &rn, Git::Reference ref, bool create); public: - void load(); - void unload(); - void findAlias(); - void scanSubmodules(); - Repo* repoByPath(const QString& basePath, bool searchSubmodules); + SPtr repoByPath(const QString& basePath, bool searchSubmodules); + WList submodules() const; public: + QMutex& mutex() const; + QString path() const; Git::Repository gitRepo(bool doLoad = false); public: - QString mPath; //!< Full, absolute path to this repository QString mDisplayAlias; //!< An alias for display (Default to last path comp.) bool mIsSubModule : 1; //!< This is a submodule of another repo bool mIsBare : 1; //!< This is a bare repo bool mIsLoaded : 1; //!< This repo is currently loaded (by gitWrap) bool mIsActive : 1; //!< This is MGV's current active repo? - bool mIsInitializing : 1; //!< True, while this repository is initializing - QTimer* mUnloadTimer; //!< NULL or a timer to unload this repository + //bool mIsInitializing : 1; //!< True, while this repository is initializing + //QTimer* mUnloadTimer; //!< NULL or a timer to unload this repository Head* mHead; //!< The HEAD private: Git::Repository mRepo; //!< GitWrap-Repo, if loaded + QString mPath; //!< Full, absolute path to this repository + mutable QMutex mMutex; //!< One mutex to protect them all (inside this Repo) + SList mSubmodules; }; + inline QMutex& Repo::mutex() const + { + return mMutex; + } + + inline Repo::WList Repo::submodules() const + { + return weakFromSharedList(mSubmodules); + } + + inline QString Repo::path() const + { + return mPath; + } + } } diff --git a/Libs/libMacGitverCore/RepoMan/Private/RepoManPrivate.hpp b/Libs/libRepoMan/Data/RepoMan.hpp similarity index 62% rename from Libs/libMacGitverCore/RepoMan/Private/RepoManPrivate.hpp rename to Libs/libRepoMan/Data/RepoMan.hpp index 2095cb9f..0b1c25f9 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/RepoManPrivate.hpp +++ b/Libs/libRepoMan/Data/RepoMan.hpp @@ -19,40 +19,34 @@ #pragma once -#include "libMacGitverCore/RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Base.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/AutoRefresher.hpp" +#include "libRepoMan/RepoMan.hpp" + +#include "libMacGitverCore/MacGitver/AutoRefresher.hpp" #include "hic_RepoManActions.h" +#if 0 // ###DEAD namespace RM { - namespace Internal + namespace Data { - class RepoManPrivate : public BasePrivate, private RepoManActions + class RepoMan : private RepoManActions { public: - RepoManPrivate(RepoMan* _pub); - - public: - ObjTypes objType() const; - bool refreshSelf(); - void preTerminate(); - QString displayName() const; - void dumpSelf(Dumper& dumper) const; - QString objectTypeName() const; + RepoMan(RepoMan* _pub); Heaven::Menu* contextMenuFor(Base* object); public: Repo::List repos; Repo* activeRepo; - AutoRefresher* refresher; }; } } +#endif diff --git a/Libs/libRepoMan/Data/Submodule.cpp b/Libs/libRepoMan/Data/Submodule.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Libs/libMacGitverCore/RepoMan/Private/RefLogPrivate.hpp b/Libs/libRepoMan/Data/Submodule.hpp similarity index 72% rename from Libs/libMacGitverCore/RepoMan/Private/RefLogPrivate.hpp rename to Libs/libRepoMan/Data/Submodule.hpp index f5945d2a..8cb02afd 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/RefLogPrivate.hpp +++ b/Libs/libRepoMan/Data/Submodule.hpp @@ -19,27 +19,30 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" +#include "libRepoMan/Data/Repo.hpp" -#include "RepoMan/RefLog.hpp" +#include "libRepoMan/Frontend/Submodule.hpp" namespace RM { - namespace Internal + namespace Data { - class RefLogPrivate : public BasePrivate + class Submodule + : public Repo { public: - RefLogPrivate(RefLog* _pub); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Submodule; + + public: + Submodule(Submodule* pub, const Git::Repository& repo); public: ObjTypes objType() const; - bool refreshSelf(); void postCreation(); void preTerminate(); - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; }; diff --git a/Libs/libRepoMan/Data/Tag.cpp b/Libs/libRepoMan/Data/Tag.cpp new file mode 100644 index 00000000..e69de29b diff --git a/Libs/libMacGitverCore/RepoMan/Private/SubmodulePrivate.hpp b/Libs/libRepoMan/Data/Tag.hpp similarity index 74% rename from Libs/libMacGitverCore/RepoMan/Private/SubmodulePrivate.hpp rename to Libs/libRepoMan/Data/Tag.hpp index 38bb9e65..6064587c 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/SubmodulePrivate.hpp +++ b/Libs/libRepoMan/Data/Tag.hpp @@ -19,26 +19,30 @@ #pragma once -#include "RepoMan/Private/RepoPrivate.hpp" +#include "libRepoMan/Data/Reference.hpp" -#include "RepoMan/Submodule.hpp" +#include "libRepoMan/Frontend/Tag.hpp" namespace RM { - namespace Internal + namespace Data { - class SubmodulePrivate : public RepoPrivate + class Tag + : public Reference { public: - SubmodulePrivate(Submodule* pub, const Git::Repository& repo); + static const_or_constexpr ObjTypes StaticObjectType = ObjTypes::Tag; + + public: + Tag(Tag* pub, const Git::Reference& _ref); public: ObjTypes objType() const; void postCreation(); void preTerminate(); - void dumpSelf(Dumper& dumper) const; + void dumpSelf(Internal::Dumper& dumper) const; QString objectTypeName() const; bool inherits(ObjTypes type) const; }; diff --git a/Libs/libRepoMan/Events/Compat.cpp b/Libs/libRepoMan/Events/Compat.cpp new file mode 100644 index 00000000..c6d704dc --- /dev/null +++ b/Libs/libRepoMan/Events/Compat.cpp @@ -0,0 +1,384 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Events/Event.hpp" +#include "libRepoMan/Events/Compat.hpp" + +namespace RM +{ + + /** + * @class CompatEventsInterface + * @brief Interface that receives all RepoMan events + * + * All pure virtual methods in this interface represent events from the RepoMan. + * + * Each of these events can be connected to individually via Qt's SIGNAL/SLOT mechanism on the + * MacGitver::repoMan() singleton. + * + * You can also write an implementation of the whole interface and register it through the + * CompatEvents singleton. We're doing that in the unit tests - and probably will do it in a + * Heaven::View in order to display the repository events. + * + * @fn CompatEventsInterface::repositoryOpened(Repo* repo) + * @brief Sent after a repository is opened + * + * This is an administrative event. It implies no actual change to the underlying repository. + * + * @param[in] repo The repository that was opened + * + * + * @fn CompatEventsInterface::repositoryAboutToClose(Repo* repo) + * @brief Sent before a repository will be closed + * + * This is an administrative event. It implies no actual change to the underlying repository. + * + * @param[in] repo The repository that is about to be closed + * + * + * @fn CompatEventsInterface::repositoryActivated(Repo* repo) + * @brief Sent after a repository was activated + * + * This is an administrative event. It implies no actual change to the underlying repository. + * + * @param[in] repo The repository that became the active one + * + * + * @fn CompatEventsInterface::repositoryDeactivated(Repo* repo) + * @brief Sent after a repository was deactivated + * + * This is an administrative event. It implies no actual change to the underlying repository. + * + * @param[in] repo The repository that was activated + * + * + * @fn CompatEventsInterface::repositoryStateChanged(Repo* repo) + * @brief Sent after a change in a repository's state was detected + * + * Transitions between "normal", "rebasing", "merging" etc. are detected. + * + * @param[in] repo The repository whose state changed + * + * @fn CompatEventsInterface::refTreeNodeCreated(Repo* repo, RefTreeNode* node) + * @brief Sent when a new tree node in a ref tree was created + * + * This is a virtual event. It is artificially created. + * + * @param[in] repo The repository for which a ref tree node was created + * @param[in] node The node that was created + * + * + * @fn CompatEventsInterface::refTreeNodeAboutToBeRemoved(Repo* repo, RefTreeNode* node) + * @brief Sent before a tree node in a ref tree will be removed + * + * This is a virtual event. It is artificially created. + * + * @param[in] repo The repository for which a ref tree node will be removed + * @param[in] node The node that will be removed + * + * + * @fn CompatEventsInterface::refCreated(Repo* repo, Ref* ref) + * @brief Sent after a reference was created + * + * @param[in] repo The affected repository + * @param[in] ref The newly created reference + * + * @fn CompatEventsInterface::refAboutToBeRemoved(Repo* repo, Ref* ref) + * @brief Sent before a reference is about to be removed + * + * The reference is most probably already physically removed. This event is sent before it is + * removed from RepoMan's data model. + * + * @param[in] repo The affected repository + * @param[in] ref The reference that will be removed + * + * + * @fn CompatEventsInterface::refMoved(Repo* repo, Ref* ref) + * @brief Sent when either the target id or the symbolic target of a reference changed. + * + * The reference is most probably already physically moved. This event is sent when the change + * is discovered by the RepoMan. + * + * @param[in] repo The affected repository + * @param[in] ref The reference that will move + * + * + * @fn CompatEventsInterface::refHeadDetached(Repo* repo, Ref* ref) + * @brief Sent after the HEAD reference got into a detached state + * + * This event will be sent when RepoMan detected that the HEAD reference has been set to a + * detached state. + * + * This will happen constantly during a rebase action and also happens after checking out a + * given SHA1 or a tag. + * + * @param[in] repo The affected repository + * @param[in] ref The HEAD reference that got detached + * + */ + + std::vector CompatEvents::mEvents; + + void CompatEvents::addReceiver(CompatEventsInterface* ev) + { + mEvents.push_back(ev); + } + + void CompatEvents::delReceiver(CompatEventsInterface* ev) + { + for (auto it = mEvents.begin(); it != mEvents.end(); ++it) { + if (*it == ev) { + mEvents.erase(it); + return; + } + } + } + + void CompatEvents::repositoryOpened(const RM::Frontend::Repo& repo) + { + for (CompatEventsInterface* ei : mEvents) { + ei->repositoryOpened(repo); + } + } + + void CompatEvents::repositoryAboutToClose(const RM::Frontend::Repo& repo) + { + for (CompatEventsInterface* ei : mEvents) { + ei->repositoryAboutToClose(repo); + } + } + + void CompatEvents::repositoryActivated(const RM::Frontend::Repo& repo) + { + for (CompatEventsInterface* ei : mEvents) { + ei->repositoryActivated(repo); + } + } + + void CompatEvents::repositoryDeactivated(const RM::Frontend::Repo& repo) + { + for (CompatEventsInterface* ei : mEvents) { + ei->repositoryDeactivated(repo); + } + } + + void CompatEvents::objectCreated(const RM::Frontend::Base& object) + { + for (CompatEventsInterface* ei : mEvents) { + ei->objectCreated(object); + } + } + + void CompatEvents::objectAboutToBeDeleted(const RM::Frontend::Base& object) + { + for (CompatEventsInterface* ei : mEvents) { + ei->objectAboutToBeDeleted(object); + } + } + + void CompatEvents::refTreeNodeCreated(const RM::Frontend::RefTreeNode& node) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refTreeNodeCreated(node); + } + } + + void CompatEvents::refTreeNodeAboutToBeDeleted(const RM::Frontend::RefTreeNode& node) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refTreeNodeAboutToBeDeleted(node); + } + } + + void CompatEvents::refCreated(const RM::Frontend::Reference& ref) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refCreated(ref); + } + } + + void CompatEvents::refAboutToBeDeleted(const RM::Frontend::Reference& ref) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refAboutToBeDeleted(ref); + } + } + + void CompatEvents::refMoved(const RM::Frontend::Reference& ref) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refMoved(ref); + } + } + + void CompatEvents::refHeadDetached(const RM::Frontend::Reference& ref) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refHeadDetached(ref); + } + } + + void CompatEvents::tagCreated(const RM::Frontend::Tag& tag) + { + for (CompatEventsInterface* ei : mEvents) { + ei->tagCreated(tag); + } + } + + void CompatEvents::tagAboutToBeDeleted(const RM::Frontend::Tag& tag) + { + for (CompatEventsInterface* ei : mEvents) { + ei->tagAboutToBeDeleted(tag); + } + } + + void CompatEvents::branchCreated(const RM::Frontend::Branch& branch) + { + for (CompatEventsInterface* ei : mEvents) { + ei->branchCreated(branch); + } + } + + void CompatEvents::branchAboutToBeDeleted(const RM::Frontend::Branch& branch) + { + for (CompatEventsInterface* ei : mEvents) { + ei->branchAboutToBeDeleted(branch); + } + } + + void CompatEvents::branchMoved(const RM::Frontend::Branch& branch) + { + for (CompatEventsInterface* ei : mEvents) { + ei->branchMoved(branch); + } + } + + void CompatEvents::branchUpstreamChanged(const RM::Frontend::Branch& branch) + { + for (CompatEventsInterface* ei : mEvents) { + ei->branchUpstreamChanged(branch); + } + } + + void CompatEvents::namespaceCreated(const RM::Frontend::Namespace& nameSpace) + { + for (CompatEventsInterface* ei : mEvents) { + ei->namespaceCreated(nameSpace); + } + } + + void CompatEvents::namespaceAboutToBeDeleted(const RM::Frontend::Namespace& nameSpace) + { + for (CompatEventsInterface* ei : mEvents) { + ei->namespaceAboutToBeDeleted(nameSpace); + } + } + + void CompatEvents::refLogChanged(const RM::Frontend::RefLog& reflog) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refLogChanged(reflog); + } + } + + void CompatEvents::refLogNewEntry(const RM::Frontend::RefLog& reflog) + { + for (CompatEventsInterface* ei : mEvents) { + ei->refLogNewEntry(reflog); + } + } + + void CompatEvents::stageCreated(const RM::Frontend::Reference& ref) + { + for (CompatEventsInterface* ei : mEvents) { + ei->stageCreated(ref); + } + } + + void CompatEvents::stageAboutToBeDeleted(const RM::Frontend::Reference& ref) + { + for (CompatEventsInterface* ei : mEvents) { + ei->stageAboutToBeDeleted(ref); + } + } + + void CompatEvents::remoteCreated(const RM::Frontend::Remote& remote) + { + for (CompatEventsInterface* ei : mEvents) { + ei->remoteCreated(remote); + } + } + + void CompatEvents::remoteAboutToBeDeleted(const RM::Frontend::Remote& remote) + { + for (CompatEventsInterface* ei : mEvents) { + ei->remoteAboutToBeDeleted(remote); + } + } + + void CompatEvents::remoteModified(const RM::Frontend::Remote& remote) + { + for (CompatEventsInterface* ei : mEvents) { + ei->remoteModified(remote); + } + } + + void CompatEvents::submoduleCreated(const RM::Frontend::Submodule& submodule) + { + for (CompatEventsInterface* ei : mEvents) { + ei->submoduleCreated(submodule); + } + } + + void CompatEvents::submoduleAboutToBeDeleted(const RM::Frontend::Submodule& submodule) + { + for (CompatEventsInterface* ei : mEvents) { + ei->submoduleAboutToBeDeleted(submodule); + } + } + + void CompatEvents::submoduleMoved(const RM::Frontend::Submodule& submodule) + { + for (CompatEventsInterface* ei : mEvents) { + ei->submoduleMoved(submodule); + } + } + + void CompatEvents::repositoryStateChanged(const RM::Frontend::Repo& repo) + { + for (CompatEventsInterface* ei : mEvents) { + ei->repositoryStateChanged(repo); + } + } + + void CompatEvents::indexUpdated() + { + for (CompatEventsInterface* ei : mEvents) { + ei->indexUpdated(); + } + } + + void CompatEvents::workTreeUpdated() + { + for (CompatEventsInterface* ei : mEvents) { + ei->workTreeUpdated(); + } + } + +} diff --git a/Libs/libRepoMan/Events/Compat.hpp b/Libs/libRepoMan/Events/Compat.hpp new file mode 100644 index 00000000..41a0dc40 --- /dev/null +++ b/Libs/libRepoMan/Events/Compat.hpp @@ -0,0 +1,123 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Frontend/Base.hpp" + +namespace RM +{ + + class REPOMAN_API CompatEventsInterface + { + public: + virtual ~CompatEventsInterface() {} + + public: + virtual void repositoryOpened(const RM::Frontend::Repo& repo) = 0; + virtual void repositoryAboutToClose(const RM::Frontend::Repo& repo) = 0; + virtual void repositoryActivated(const RM::Frontend::Repo& repo) = 0; + virtual void repositoryDeactivated(const RM::Frontend::Repo& repo) = 0; + + virtual void objectCreated(const RM::Frontend::Base& object) = 0; + virtual void objectAboutToBeDeleted(const RM::Frontend::Base& object) = 0; + + virtual void refTreeNodeCreated(const RM::Frontend::RefTreeNode& node) = 0; + virtual void refTreeNodeAboutToBeDeleted(const RM::Frontend::RefTreeNode& node) = 0; + + virtual void refCreated(const RM::Frontend::Reference& ref) = 0; + virtual void refAboutToBeDeleted(const RM::Frontend::Reference& ref) = 0; + virtual void refMoved(const RM::Frontend::Reference& ref) = 0; + virtual void refHeadDetached(const RM::Frontend::Reference& ref) = 0; + + virtual void tagCreated(const RM::Frontend::Tag& tag) = 0; + virtual void tagAboutToBeDeleted(const RM::Frontend::Tag& tag) = 0; + + virtual void branchCreated(const RM::Frontend::Branch& branch) = 0; + virtual void branchAboutToBeDeleted(const RM::Frontend::Branch& branch) = 0; + virtual void branchMoved(const RM::Frontend::Branch& branch) = 0; + virtual void branchUpstreamChanged(const RM::Frontend::Branch& branch) = 0; + + virtual void namespaceCreated(const RM::Frontend::Namespace& nameSpace) = 0; + virtual void namespaceAboutToBeDeleted(const RM::Frontend::Namespace& nameSpace) = 0; + + virtual void refLogChanged(const RM::Frontend::RefLog& reflog) = 0; + virtual void refLogNewEntry(const RM::Frontend::RefLog& reflog) = 0; + + virtual void stageCreated(const RM::Frontend::Reference& ref) = 0; + virtual void stageAboutToBeDeleted(const RM::Frontend::Reference& ref) = 0; + + virtual void remoteCreated(const RM::Frontend::Remote& remote) = 0; + virtual void remoteAboutToBeDeleted(const RM::Frontend::Remote& remote) = 0; + virtual void remoteModified(const RM::Frontend::Remote& remote) = 0; + + virtual void submoduleCreated(const RM::Frontend::Submodule& submodule) = 0; + virtual void submoduleAboutToBeDeleted(const RM::Frontend::Submodule& submodule) = 0; + virtual void submoduleMoved(const RM::Frontend::Submodule& submodule) = 0; + + virtual void repositoryStateChanged(const RM::Frontend::Repo& repo) = 0; + virtual void indexUpdated() = 0; + virtual void workTreeUpdated() = 0; + }; + + class REPOMAN_API CompatEvents + { + static std::vector mEvents; + + public: + static void addReceiver(CompatEventsInterface* ei); + static void delReceiver(CompatEventsInterface* ei); + + public: + static void repositoryOpened(const RM::Frontend::Repo& repo); + static void repositoryAboutToClose(const RM::Frontend::Repo& repo); + static void repositoryActivated(const RM::Frontend::Repo& repo); + static void repositoryDeactivated(const RM::Frontend::Repo& repo); + static void objectCreated(const RM::Frontend::Base& object); + static void objectAboutToBeDeleted(const RM::Frontend::Base& object); + static void refTreeNodeCreated(const RM::Frontend::RefTreeNode& node); + static void refTreeNodeAboutToBeDeleted(const RM::Frontend::RefTreeNode& node); + static void refCreated(const RM::Frontend::Reference& ref); + static void refAboutToBeDeleted(const RM::Frontend::Reference& ref); + static void refMoved(const RM::Frontend::Reference& ref); + static void refHeadDetached(const RM::Frontend::Reference& ref); + static void tagCreated(const RM::Frontend::Tag& tag); + static void tagAboutToBeDeleted(const RM::Frontend::Tag& tag); + static void branchCreated(const RM::Frontend::Branch& branch); + static void branchAboutToBeDeleted(const RM::Frontend::Branch& branch); + static void branchMoved(const RM::Frontend::Branch& branch); + static void branchUpstreamChanged(const RM::Frontend::Branch& branch); + static void namespaceCreated(const RM::Frontend::Namespace& nameSpace); + static void namespaceAboutToBeDeleted(const RM::Frontend::Namespace& nameSpace); + static void refLogChanged(const RM::Frontend::RefLog& reflog); + static void refLogNewEntry(const RM::Frontend::RefLog& reflog); + static void stageCreated(const RM::Frontend::Reference& ref); + static void stageAboutToBeDeleted(const RM::Frontend::Reference& ref); + static void remoteCreated(const RM::Frontend::Remote& remote); + static void remoteAboutToBeDeleted(const RM::Frontend::Remote& remote); + static void remoteModified(const RM::Frontend::Remote& remote); + static void submoduleCreated(const RM::Frontend::Submodule& submodule); + static void submoduleAboutToBeDeleted(const RM::Frontend::Submodule& submodule); + static void submoduleMoved(const RM::Frontend::Submodule& submodule); + static void repositoryStateChanged(const RM::Frontend::Repo& repo); + static void indexUpdated(); + static void workTreeUpdated(); + }; + +} diff --git a/Libs/libRepoMan/Events/Event.cpp b/Libs/libRepoMan/Events/Event.cpp new file mode 100644 index 00000000..3d5b0fdd --- /dev/null +++ b/Libs/libRepoMan/Events/Event.cpp @@ -0,0 +1,93 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Events/Event.hpp" +#include "libRepoMan/Events/EventData.hpp" + +#include "libRepoMan/Frontend/Repo.hpp" + +namespace RM +{ + + + Event::Event() + { + } + + Event::~Event() + { + } + + Event::Event(const Event& o) + : d(o.d) + { + } + + Event::Event(Event&& o) + : d(std::move(o.d)) + { + } + + Event::Event(const std::shared_ptr& o) + : d(o) + { + } + + Event::Event(std::shared_ptr&& o) + : d(std::move(o)) + { + } + + Event& Event::operator =(const Event& o) + { + d = o.d; + return *this; + } + + Event& Event::operator =(Event&& o) + { + d = std::move(o.d); + return *this; + } + + EventType Event::type() const + { + if (!d) { + return EventType::None; + } + return d->type(); + } + + Frontend::Repo Event::repo() const + { + if (!d) { + return Frontend::Repo(); + } + return d->repo().lock(); + } + + Frontend::Base Event::baseContext() const + { + if (!d) { + return Frontend::Base(); + } + return d->context(); + } + +} diff --git a/Libs/libRepoMan/Events/Event.hpp b/Libs/libRepoMan/Events/Event.hpp new file mode 100644 index 00000000..3c2d2dad --- /dev/null +++ b/Libs/libRepoMan/Events/Event.hpp @@ -0,0 +1,74 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Frontend/Base.hpp" + +#include + +namespace RM +{ + + namespace Internal + { + class EventData; + } + + enum class EventType + { + None, + + RepoOpened, + RepoAboutToClose, + RepoActivated, + RepoDeactivated, + }; + + class REPOMAN_API Event + { + public: + Event(); + Event(std::shared_ptr&& d); + Event(const std::shared_ptr& d); + Event(const Event& o); + Event(Event&& o); + + Event& operator=(const Event& o); + Event& operator=(Event&& o); + + ~Event(); + + public: + EventType type() const; + Frontend::Repo repo() const; + + Frontend::Base baseContext() const; + + template + T context() const + { + return baseContext().as(); + } + + private: + std::shared_ptr d; + }; + +} diff --git a/Libs/libRepoMan/Events/EventData.cpp b/Libs/libRepoMan/Events/EventData.cpp new file mode 100644 index 00000000..298767cc --- /dev/null +++ b/Libs/libRepoMan/Events/EventData.cpp @@ -0,0 +1,49 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Events/EventData.hpp" + +namespace RM +{ + + namespace Internal + { + + EventData::EventData(EventType type, Data::Base* context) + : mType(type) + , mContext(context ? context->getPtr() : Data::Base::SPtr()) + { + } + + std::shared_ptr EventData::create(EventType type, Data::Base* context) + { + return std::make_shared(type, context); + } + + Data::Repo::WPtr EventData::repo() const + { + if (!mContext) { + return Data::Repo::WPtr(); + } + return mContext->repository(); + } + + } + +} diff --git a/Libs/libRepoMan/Events/EventData.hpp b/Libs/libRepoMan/Events/EventData.hpp new file mode 100644 index 00000000..4539d8a4 --- /dev/null +++ b/Libs/libRepoMan/Events/EventData.hpp @@ -0,0 +1,55 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Events/Event.hpp" +#include "libRepoMan/Data/Base.hpp" +#include "libRepoMan/Data/Repo.hpp" + +namespace RM +{ + + namespace Internal + { + + class EventData + { + public: + EventData() = delete; + EventData(const EventData&) = delete; + EventData(EventType type, Data::Base* context); + + public: + static std::shared_ptr create(EventType type, Data::Base* context); + + public: + Data::Repo::WPtr repo() const; + const Data::Base::SPtr& context() const { return mContext; } + EventType type() const { return mType; } + + private: + EventType mType; + Data::Base::SPtr mContext; + }; + + + } + +} diff --git a/Libs/libRepoMan/Events/Manager.cpp b/Libs/libRepoMan/Events/Manager.cpp new file mode 100644 index 00000000..1b7ab1c9 --- /dev/null +++ b/Libs/libRepoMan/Events/Manager.cpp @@ -0,0 +1,71 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Events/Manager.hpp" + +#include +#include +#include +#include + +namespace RM +{ + + namespace Internal + { + + void ThreadMover::sendMovedEvent(const Event& e) + { + Q_ASSERT(QThread::currentThread() == thread()); + EventManager::self().sendEvent(e); + } + + } + + EventManager::EventManager() + { + if(thread() != qApp->thread()) { + qDebug() << "Moving EventManager to main thread"; + moveToThread(qApp->thread()); + } + + mMover = new Internal::ThreadMover(this); + } + + void EventManager::sendEvent(const Event& ev) + { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(mMover, "sendMovedEvent", Qt::QueuedConnection, + Q_ARG(RM::Event, ev)); + return; + } + emit repoEvent(ev); + } + + EventManager& EventManager::self() + { + static QPointer s; + if (!s) { + s = new EventManager; + } + return *s; + } + +} + diff --git a/Libs/libRepoMan/Events/Manager.hpp b/Libs/libRepoMan/Events/Manager.hpp new file mode 100644 index 00000000..83d3fdc0 --- /dev/null +++ b/Libs/libRepoMan/Events/Manager.hpp @@ -0,0 +1,62 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Events/Event.hpp" + +namespace RM +{ + + namespace Internal + { + + class ThreadMover : public QObject + { + Q_OBJECT + public: + using QObject::QObject; + + public slots: + void sendMovedEvent(const RM::Event& e); + }; + + } + + class REPOMAN_API EventManager + : public QObject + { + Q_OBJECT + public: + static EventManager& self(); + + private: + EventManager(); + + public: + void sendEvent(const Event& ev); + + signals: + void repoEvent(const Event& ev); + + private: + Internal::ThreadMover* mMover; + }; + +} diff --git a/Libs/libRepoMan/Frontend/Base.cpp b/Libs/libRepoMan/Frontend/Base.cpp new file mode 100644 index 00000000..bbe40354 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Base.cpp @@ -0,0 +1,250 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +//#include "App/MacGitver.hpp" + +#include "libRepoMan/Frontend/BaseInternal.hpp" +#include "libRepoMan/Frontend/Repo.hpp" +#include "libRepoMan/RepoMan.hpp" +#include "libRepoMan/Frontend/RefTreeNode.hpp" + +#include "libRepoMan/Events/Event.hpp" + +#include "libRepoMan/Data/Base.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libHeavenIcons/IconRef.hpp" + +#include +#include + +/** + * @class RM::Frontend::Base + * @brief Base class for all RepoMan objects + * + * This base class takes care of a unified linking between a parent and its children. Children + * are always created with a pointer to their parent. Children may never be reparented. Only a + * parent is allowed to create children for itself. + * + * Further, the Base class takes care of keeping the strict logic of the refresh process. For + * details on how to implement the refresh logic, see refresh(). + * + * Finally, this base class allows to dump a partial subtree of RepoMan objects into a textual + * hierarchy. See dump() on advanced information. + * + */ + +namespace RM +{ + + namespace Frontend + { + + /** + * @brief Constructor + * + * Creates a new RepoMan object and links it into the parent. Because at this point the new + * child is not yet fully constructed, no further action is taken. + * + * @param[in] parent The parent to whom we shall link this new child to. + * + */ + Base::Base(const std::shared_ptr& d) + : mData(d) + { + } + + Base::Base(std::shared_ptr&& d) + : mData(std::move(d)) + { + } + + Base::Base() + {} + + Base::Base(const Base& other) + : mData(other.mData) + { + } + + Base::Base(Base&& other) + : mData(std::move(other.mData)) + { + } + + Base& Base::operator=(Base&& other) + { + std::swap(mData, other.mData); + return * this; + } + + bool Base::operator==(const Base& other) const + { + return mData == other.mData; + } + + Base::operator bool() const + { + return !!mData; + } + /** + * @brief Destructor + * + * At the point where the destructor is called, all children should have been unlinked from the + * tree and this object has to be unlinked too. + * + */ + Base::~Base() + { + } + + Base& Base::operator=(const Base& other) + { + mData = other.mData; + return * this; + } + + /** + * @brief Get the direct parent object + * + * The direct parent object is specified during construction and can never be changed. + * + * @return The direct parent object. + * + */ + Base Base::parent() const + { + return mData->parent(); + } + + /** + * @brief Find the repository for this object + * + * @return The first repository in hierarchy (Repo or Submodule) + * + */ + Repo Base::repository() const + { + if (mData) { + return mData->repository().lock(); + } + return Repo(); + } + + bool Base::inherits(ObjTypes type) const + { + return mData->inherits(type); + } + + /** + * @brief Get the type of this object + * + * This method must be implemented by all derivats of Base. They must simply return the correct + * value from the ObjTypes enum. + * + * @return Type of this object + * + */ + ObjTypes Base::objType() const + { + return mData->objType(); + } + + /** + * @brief Creates a textual dump of this object and its children + * + * @return Textual dump. + * + */ + QString Base::dump() const + { + Internal::Dumper dumper; + mData->dumpRecursive(dumper); + return dumper.output(); + } + + /** + * @brief Get the name of this object type + * + * @return The name + * + */ + QString Base::typeName() const + { + return mData->objectTypeName(); + } + + std::shared_ptr Base::data() const + { + return mData; + } + + Base::List Base::children() const + { + // ###REPOMAN Do we need to lock here? + if (mData) { + //return mData->children(); + } + + return List(); + } + + /** + * @brief Get a string that can be used to display this object + * + * @return Always ``. Reimplementations should return something more meaningful. + * + */ + QString Base::displayName() const + { + DPtrT d(this); + return d->displayName(); + } + + #if 0 // ###DEAD + /** + * @brief Get a context menu for this object + * + * @return A Heaven::Menu that can be used as context menu for this object. + * + */ + Heaven::Menu* Base::contextMenu() + { + RepoMan* rm = &MacGitver::repoMan(); + RepoMan::Private* rmp = BasePrivate::dataOf(rm); + return rmp->contextMenuFor(this); + } + #endif + + /** + * @brief Get an icon for this object + * + * @return A iconRef for this object + * + */ + Heaven::IconRef Base::icon(bool small) const + { + DPtrT d(this); + return d->icon(small); + } + + } + +} diff --git a/Libs/libRepoMan/Frontend/Base.hpp b/Libs/libRepoMan/Frontend/Base.hpp new file mode 100644 index 00000000..2029dbe0 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Base.hpp @@ -0,0 +1,110 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Core.hpp" + +namespace RM +{ + + namespace Internal + { + class Dumper; + } + + namespace Data + { + class Base; + } + + namespace Frontend + { + + class REPOMAN_API Base + { + public: + using List = std::vector; + using DPtrType = Data::Base; + + public: + Base(const std::shared_ptr& d); + Base(std::shared_ptr&& d); + virtual ~Base(); + Base(); + + public: + Base(const Base& other); + Base(Base&& other); + Base& operator=(const Base& other); + Base& operator=(Base&& other); + + bool operator==(const Base& other) const; + + operator bool() const; + + public: + ObjTypes objType() const; + bool inherits(ObjTypes type) const; + + public: + Repo repository() const; + Base parent() const; + + Heaven::IconRef icon(bool small = false) const; + + QString typeName() const; + QString displayName() const; + QString dump() const; + + Heaven::Menu* contextMenu(); + + std::shared_ptr data() const; + + template + T as() const; + + List children() const; + + protected: + std::shared_ptr mData; + + protected: + enum LockingMechanism { Locked, NotLocked }; + + private: + template + struct Locker; + + protected: + template + class DPtrT; + }; + + template + inline T Base::as() const + { + using Dest = typename T::DPtrType; + const Dest* p = std::static_pointer_cast(mData); + return T(p); + } + + } + +} diff --git a/Libs/libRepoMan/Frontend/BaseInternal.hpp b/Libs/libRepoMan/Frontend/BaseInternal.hpp new file mode 100644 index 00000000..78a1446b --- /dev/null +++ b/Libs/libRepoMan/Frontend/BaseInternal.hpp @@ -0,0 +1,121 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Frontend/Base.hpp" +#include "libRepoMan/Backend/RepoLocker.hpp" + +namespace RM +{ + namespace Frontend + { + + template + struct Base::Locker + { + /* constexpr */ Locker(const std::shared_ptr&) + {} + }; + + template<> + struct Base::Locker + : private Backend::RepoLocker + { + public: + Locker(const std::shared_ptr& t) + : Backend::RepoLocker(std::const_pointer_cast(t)) + {} + }; + + template + class Base::DPtrT + { + public: + using DPtrType = typename T::DPtrType; + + public: + DPtrT(T* that); + + public: + const DPtrType* operator->() const { return d.get(); } + DPtrType* operator->() { return d.get(); } + operator const DPtrType*() const { return d.get(); } + operator DPtrType*() { return d.get(); } + + private: + std::shared_ptr d; + Base::Locker l; + }; + + template + inline Base::DPtrT::DPtrT(T* that) + : d(std::static_pointer_cast(that->mData)) + , l(d->repository().lock()) + { + } + + template + class Base::DPtrT + { + public: + using DPtrType = typename T::DPtrType; + + public: + DPtrT(const T* that); + + public: + const DPtrType* operator->() const { return d.get(); } + operator const DPtrType*() const { return d.get(); } + + private: + std::shared_ptr d; + Base::Locker l; + }; + + template + inline Base::DPtrT::DPtrT(const T* that) + : d(std::static_pointer_cast(that->mData)) + , l(d->repository().lock()) + { + } + + template + inline typename T::List toFrontend(const typename T::DPtrType::SList& slist) + { + typename T::List frontendlist; + for (const typename T::DPtrType::SPtr& s : slist) { + frontendlist.push_back(T(s)); + } + return frontendlist; + } + + template + inline typename T::List toFrontend(const typename T::DPtrType::WList& wlist) + { + typename T::List frontendlist; + for (const typename T::DPtrType::WPtr& w : wlist) { + frontendlist.push_back(T(w.lock())); + } + return frontendlist; + } + + } + +} diff --git a/Libs/libRepoMan/Frontend/Branch.cpp b/Libs/libRepoMan/Frontend/Branch.cpp new file mode 100644 index 00000000..5db6a411 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Branch.cpp @@ -0,0 +1,80 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Frontend/Branch.hpp" +#include "libRepoMan/Frontend/Repo.hpp" +#include "libRepoMan/Frontend/Head.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libRepoMan/Data/Branch.hpp" + +namespace RM +{ + + namespace Frontend + { + + #if 0 + Branch::Branch(Base* parent, const Git::Reference &ref) + : Reference( *new Data::Branch(this, ref) ) + { + RM_D(Branch); + d->linkToParent( parent ); + } + + QString Branch::upstreamRefName() const + { + RM_CD(Branch); + return d->mUpstreamRefName; + } + + Reference Branch::upstream() + { + return repository().findReference(upstreamRefName()); + } + + bool Branch::hasUpstream() const + { + RM_CD(Branch); + return d->mHasUpstream; + } + + int Branch::aheadCount() const + { + RM_CD(Branch); + return d->mAheadCount; + } + + int Branch::behindCount() const + { + RM_CD(Branch); + return d->mBehindCount; + } + + bool Branch::isHead() const + { + const Repo* r = repository(); + const Head* h = r ? r->head() : NULL; + return h && h->is(this); + } + #endif + } + +} diff --git a/Libs/libRepoMan/Frontend/Branch.hpp b/Libs/libRepoMan/Frontend/Branch.hpp new file mode 100644 index 00000000..38abdabe --- /dev/null +++ b/Libs/libRepoMan/Frontend/Branch.hpp @@ -0,0 +1,50 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Frontend/Reference.hpp" + +namespace RM +{ + + namespace Frontend + { + + class REPOMAN_API Branch : public Reference + { + public: + static const ObjTypes StaticObjectType = ObjTypes::Branch; + typedef QVector List; + + public: + Branch(Base* parent, const Git::Reference& ref); + + public: + bool hasUpstream() const; + QString upstreamRefName() const; + Reference upstream(); + int aheadCount() const; + int behindCount() const; + bool isHead() const; + }; + + } + +} diff --git a/Libs/libRepoMan/Frontend/Head.cpp b/Libs/libRepoMan/Frontend/Head.cpp new file mode 100644 index 00000000..c59079ff --- /dev/null +++ b/Libs/libRepoMan/Frontend/Head.cpp @@ -0,0 +1,86 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libRepoMan/Data/Head.hpp" + +#include "libRepoMan/Frontend/Branch.hpp" +#include "libRepoMan/Frontend/Repo.hpp" + +#include "libGitWrap/Repository.hpp" + +namespace RM +{ + + namespace Frontend + { + + #if 0 + Head::Head(const Git::Repository& repo, Base* parent) + : Base(*new Internal::HeadPrivate(this, repo)) + { + RM_D(Head); + d->linkToParent(parent); + } + + QString Head::symbolicName() const + { + RM_CD(Head); + if (d->isDetached) { + return QString(); + } + return d->symbolicName; + } + + bool Head::isDetached() const + { + RM_CD(Head); + return d->isDetached; + } + + bool Head::isUnborn() const + { + RM_CD(Head); + return d->isUnborn; + } + + Git::ObjectId Head::detachedId() const + { + RM_CD(Head); + return d->detachedId; + } + + bool Head::is(const Branch* ref) const + { + RM_CD(Head); + + if (d->isDetached || d->isUnborn) { + /* If it's unborn, it cannot match an existing branch anyway */ + return false; + } + + return ref && d->symbolicName == ref->fullName(); + } + + #endif + + } + +} diff --git a/Libs/libRepoMan/Frontend/Head.hpp b/Libs/libRepoMan/Frontend/Head.hpp new file mode 100644 index 00000000..6478e4b9 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Head.hpp @@ -0,0 +1,56 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Frontend/Branch.hpp" + +namespace RM +{ + + namespace Data + { + class Head; + } + + namespace Frontend + { + class REPOMAN_API Head : public Base + { + public: + static const ObjTypes StaticObjectType = ObjTypes::Head; + typedef Data::Head Private; + typedef QVector List; + + public: + Head(const Git::Repository& repo, Base* parent); + + public: + bool isDetached() const; + bool isUnborn() const; + Git::ObjectId detachedId() const; + QString symbolicName() const; + + public: + bool is(const Branch* ref) const; + }; + + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/Namespace.cpp b/Libs/libRepoMan/Frontend/Namespace.cpp similarity index 62% rename from Libs/libMacGitverCore/RepoMan/Namespace.cpp rename to Libs/libRepoMan/Frontend/Namespace.cpp index 19ba0b7e..ae2251bd 100644 --- a/Libs/libMacGitverCore/RepoMan/Namespace.cpp +++ b/Libs/libRepoMan/Frontend/Namespace.cpp @@ -17,58 +17,63 @@ * */ -#include "Namespace.hpp" -#include "Events.hpp" +#include "libRepoMan/Frontend/Namespace.hpp" -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/NamespacePrivate.hpp" +#include "libRepoMan/Private/Dumper.hpp" +#include "libRepoMan/Data/Namespace.hpp" namespace RM { - using namespace Internal; - - Namespace::Namespace(Base* _parent, const QString& _name) - : Base(*new NamespacePrivate(this, _name)) + namespace Frontend { - RM_D(Namespace); - d->linkToParent(_parent); - } - CollectionNode* Namespace::branches() - { - RM_D(Namespace); + #if 0 + Namespace::Namespace(Base* _parent, const QString& _name) + : Base(*new NamespacePrivate(this, _name)) + { + RM_D(Namespace); + d->linkToParent(_parent); + } - return d->getOrCreateCollection( ctBranches ); - } + CollectionNode* Namespace::branches() + { + RM_D(Namespace); - CollectionNode* Namespace::tags() - { - RM_D(Namespace); - return d->getOrCreateCollection( ctTags ); - } + return d->getOrCreateCollection( ctBranches ); + } - CollectionNode* Namespace::namespaces() - { - RM_D(Namespace); + CollectionNode* Namespace::tags() + { + RM_D(Namespace); + return d->getOrCreateCollection( ctTags ); + } - return d->getOrCreateCollection( ctNamespaces ); - } + CollectionNode* Namespace::namespaces() + { + RM_D(Namespace); - CollectionNode* Namespace::notes() - { - RM_D(Namespace); + return d->getOrCreateCollection( ctNamespaces ); + } - return d->getOrCreateCollection( ctNotes ); - } + CollectionNode* Namespace::notes() + { + RM_D(Namespace); - QString Namespace::name() const - { - RM_D(Namespace); + return d->getOrCreateCollection( ctNotes ); + } + + QString Namespace::name() const + { + RM_D(Namespace); + + return d->name; + } + #endif - return d->name; } +#if 0 //-- NamespacePrivate -------------------------------------------------------------------------- NamespacePrivate::NamespacePrivate(Namespace* _pub, const QString& _name) @@ -79,7 +84,7 @@ namespace RM ObjTypes NamespacePrivate::objType() const { - return NamespaceObject; + return ObjTypes::Namespace; } void NamespacePrivate::dumpSelf(Internal::Dumper& dumper) const @@ -124,7 +129,9 @@ namespace RM bool NamespacePrivate::inherits(ObjTypes type) const { - return type == NamespaceObject || BasePrivate::inherits(type); + return type == ObjTypes::Namespace || BasePrivate::inherits(type); } + #endif + } diff --git a/Libs/libMacGitverCore/RepoMan/Private/HeadPrivate.hpp b/Libs/libRepoMan/Frontend/Namespace.hpp similarity index 57% rename from Libs/libMacGitverCore/RepoMan/Private/HeadPrivate.hpp rename to Libs/libRepoMan/Frontend/Namespace.hpp index 2b67f393..39c02ddf 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/HeadPrivate.hpp +++ b/Libs/libRepoMan/Frontend/Namespace.hpp @@ -19,36 +19,40 @@ #pragma once -#include "RepoMan/Private/BasePrivate.hpp" - -#include "RepoMan/Head.hpp" +#include "libRepoMan/Frontend/Base.hpp" namespace RM { - namespace Internal + namespace Data + { + class Namespace; + } + + namespace Frontend { - class HeadPrivate : public BasePrivate + class REPOMAN_API Namespace : public Base { public: - HeadPrivate(Head* pub, const Git::Repository& ref); + static const ObjTypes StaticObjectType = ObjTypes::Namespace; + typedef Data::Namespace Private; + typedef QVector List; public: - ObjTypes objType() const; - bool refreshSelf(); - QString displayName() const; - void dumpSelf(Dumper& dumper) const; - QString objectTypeName() const; - bool inherits(ObjTypes type) const; + Namespace(Base* parent, const QString& _name); public: - QString symbolicName; - Git::ObjectId detachedId; - bool isDetached : 1; - bool isUnborn : 1; - }; + QString name() const; + #if 0 // ###DEAD + public: + CollectionNode* branches(); + CollectionNode* namespaces(); + CollectionNode* notes(); + CollectionNode* tags(); + #endif + }; } } diff --git a/Libs/libRepoMan/Frontend/RefLog.cpp b/Libs/libRepoMan/Frontend/RefLog.cpp new file mode 100644 index 00000000..bcacc3ac --- /dev/null +++ b/Libs/libRepoMan/Frontend/RefLog.cpp @@ -0,0 +1,95 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Frontend/RefLog.hpp" + +#include "libRepoMan/Data/RefLog.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +namespace RM +{ + + namespace Frontend + { + + #if 0 + + RefLog::RefLog(Base* _parent) + : Base(*new RefLogPrivate(this)) + { + RM_D(RefLog); + d->linkToParent(_parent); + } + + #endif + + } + + namespace Data + { + + #if 0 + + RefLogPrivate::RefLogPrivate(RefLog* _pub) + : BasePrivate(_pub) + { + } + + ObjTypes RefLogPrivate::objType() const + { + return RefLogObject; + } + + void RefLogPrivate::dumpSelf(Internal::Dumper& dumper) const + { + dumper.addLine(QString(QLatin1String("RefLog 0x%1")) + .arg(quintptr(mPub),0,16)); + } + + void RefLogPrivate::postCreation() + { + BasePrivate::postCreation(); + } + + void RefLogPrivate::preTerminate() + { + // What to do? We don't send Ref-Log-Deleted events + BasePrivate::preTerminate(); + } + + bool RefLogPrivate::refreshSelf() + { + return true; + } + + QString RefLogPrivate::objectTypeName() const + { + return QLatin1String("RefLog"); + } + + bool RefLogPrivate::inherits(ObjTypes type) const + { + return type == RefLogObject || BasePrivate::inherits(type); + } + + #endif + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/Submodule.hpp b/Libs/libRepoMan/Frontend/RefLog.hpp similarity index 66% rename from Libs/libMacGitverCore/RepoMan/Submodule.hpp rename to Libs/libRepoMan/Frontend/RefLog.hpp index 2d366d7d..8d375456 100644 --- a/Libs/libMacGitverCore/RepoMan/Submodule.hpp +++ b/Libs/libRepoMan/Frontend/RefLog.hpp @@ -19,27 +19,30 @@ #pragma once -#include "Repo.hpp" +#include "libRepoMan/Frontend/Base.hpp" namespace RM { - class MGV_CORE_API Submodule : public Repo + namespace Data { - public: - enum { StaticObjectType = SubmoduleObject }; + class RefLog; + } - public: - Submodule(const Git::Repository& repo, Repo* parent); + namespace Frontend + { - public: + class REPOMAN_API RefLog + : public Base + { + public: + static const ObjTypes StaticObjectType = ObjTypes::RefLog; + typedef Data::RefLog Private; - private: - ObjTypes objType() const; - void preTerminate(); - void dumpSelf(Internal::Dumper& dumper) const; + public: + RefLog(Base* _parent); + }; - private: - }; + } } diff --git a/Libs/libRepoMan/Frontend/RefTreeNode.cpp b/Libs/libRepoMan/Frontend/RefTreeNode.cpp new file mode 100644 index 00000000..140da7e8 --- /dev/null +++ b/Libs/libRepoMan/Frontend/RefTreeNode.cpp @@ -0,0 +1,118 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Frontend/RefTreeNode.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libRepoMan/Data/RefTreeNode.hpp" + +namespace RM +{ + + namespace Frontend + { + + #if 0 + RefTreeNode::RefTreeNode(Base* _parent, const QString& _name) + : Base(*new RefTreeNodePrivate(this, _name)) + { + RM_D(RefTreeNode); + d->linkToParent(_parent); + } + + QString RefTreeNode::name() const + { + RM_D(RefTreeNode); + + return d->name; + } + #endif + + } + + namespace Data + { + #if 0 + RefTreeNodePrivate::RefTreeNodePrivate(RefTreeNode* _pub, const QString& _name) + : BasePrivate(_pub) + , name(_name) + { + } + + ObjTypes RefTreeNodePrivate::objType() const + { + return RefTreeNodeObject; + } + + void RefTreeNodePrivate::dumpSelf(Dumper& dumper) const + { + dumper.addLine(QString(QLatin1String("RefTreeNode 0x%1 [%2]")) + .arg(quintptr(mPub),0,16) + .arg(name)); + } + + void RefTreeNodePrivate::postCreation() + { + if (!repoEventsBlocked()) { + Events::self()->refTreeNodeCreated(repository(), pub()); + } + + BasePrivate::postCreation(); + } + + void RefTreeNodePrivate::preTerminate() + { + if (!repoEventsBlocked()) { + Events::self()->refTreeNodeAboutToBeDeleted(repository(), pub()); + } + + BasePrivate::preTerminate(); + } + + QString RefTreeNodePrivate::displayName() const + { + return name; + } + + bool RefTreeNodePrivate::refreshSelf() + { + // We don't have anything to refresh - we're purely virutual + return true; + } + + bool RefTreeNodePrivate::refreshCheckDispensable() + { + return mChildren.isEmpty(); + } + + QString RefTreeNodePrivate::objectTypeName() const + { + return QLatin1String("RefTreeNode"); + } + + bool RefTreeNodePrivate::inherits(ObjTypes type) const + { + return type == RefTreeNodeObject || BasePrivate::inherits(type); + } + #endif + + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/RefTreeNode.hpp b/Libs/libRepoMan/Frontend/RefTreeNode.hpp similarity index 64% rename from Libs/libMacGitverCore/RepoMan/RefTreeNode.hpp rename to Libs/libRepoMan/Frontend/RefTreeNode.hpp index be0f5455..4e08c9c4 100644 --- a/Libs/libMacGitverCore/RepoMan/RefTreeNode.hpp +++ b/Libs/libRepoMan/Frontend/RefTreeNode.hpp @@ -19,9 +19,9 @@ #pragma once -#include +#include "libRepoMan/Frontend/Base.hpp" -#include "Base.hpp" +#include namespace RM { @@ -31,19 +31,24 @@ namespace RM class RefTreeNodePrivate; } - class MGV_CORE_API RefTreeNode : public Base + namespace Frontend { - public: - enum { StaticObjectType = RefTreeNodeObject }; - typedef Internal::RefTreeNodePrivate Private; - typedef QSet< RefTreeNode* > Set; - typedef QList< RefTreeNode* > List; - - public: - RefTreeNode(Base* _parent, const QString& _name); - - public: - QString name() const; - }; + + class REPOMAN_API RefTreeNode + : public Base + { + public: + static const ObjTypes StaticObjectType = ObjTypes::RefTreeNode; + typedef Internal::RefTreeNodePrivate Private; + typedef QList< RefTreeNode* > List; + + public: + RefTreeNode(Base* _parent, const QString& _name); + + public: + QString name() const; + }; + + } } diff --git a/Libs/libMacGitverCore/RepoMan/Ref.cpp b/Libs/libRepoMan/Frontend/Reference.cpp similarity index 52% rename from Libs/libMacGitverCore/RepoMan/Ref.cpp rename to Libs/libRepoMan/Frontend/Reference.cpp index 4bcdd5dd..831c2988 100644 --- a/Libs/libMacGitverCore/RepoMan/Ref.cpp +++ b/Libs/libRepoMan/Frontend/Reference.cpp @@ -21,76 +21,90 @@ #include "libGitWrap/Reference.hpp" #include "libGitWrap/RefName.hpp" -#include "Ref.hpp" -#include "Repo.hpp" -#include "Events.hpp" +#include "libRepoMan/Frontend/BaseInternal.hpp" +#include "libRepoMan/Frontend/Reference.hpp" +#include "libRepoMan/Frontend/Repo.hpp" -#include "Private/Dumper.hpp" -#include "Private/RefPrivate.hpp" +#include "libRepoMan/Data/Reference.hpp" + +#include "libRepoMan/Private/Dumper.hpp" namespace RM { - //-- Ref --8> - - Ref::Ref(Internal::RefPrivate& data) - : Base( data ) + namespace Frontend { - } - Ref::Ref(Base* parent, RefTypes type, const Git::Reference& ref) - : Base( *new Internal::RefPrivate( this, type, ref ) ) - { - RM_D( Ref ); - d->linkToParent( parent ); - } + #if 0 - RefTypes Ref::type() const - { - RM_CD(Ref); - return d->mType; - } + Reference::Reference(Data::Reference* data) + : Base(data) + { + } - QString Ref::name() const - { - RM_CD(Ref); - return d->mName; - } + Reference::Reference(Base* parent, RefTypes type, const Git::Reference& ref) + : Base( *new Internal::RefPrivate( this, type, ref ) ) + { + RM_D(Reference); + d->linkToParent( parent ); + } + #endif - QString Ref::fullName() const - { - RM_CD(Ref); - return d->mFullQualifiedName; - } + RefTypes Reference::type() const + { + DPtrT d(this); + return d->mType; + } - Git::ObjectId Ref::id() const - { - RM_CD(Ref); - return d->mId; - } + QString Reference::name() const + { + DPtrT d(this); + return d->mName; + } - QString Ref::displaySha1() const - { - return id().toString(8); - } + QString Reference::fullName() const + { + DPtrT d(this); + return d->mFullQualifiedName; + } - Git::Reference Ref::load(Git::Result& r) - { - RM_D(Ref); - Git::Reference gitRef; + Git::ObjectId Reference::id() const + { + DPtrT d(this); + return d->mId; + } + + QString Reference::displaySha1() const + { + return id().toString(8); + } + + #if 0 + + Git::Reference Reference::load(Git::Result& r) + { + RM_D(Ref); + Git::Reference gitRef; + + if (r) { + Git::Repository repo = repository()->gitRepo(); + gitRef = repo.reference(r, d->mFullQualifiedName); + } - if (r) { - Git::Repository repo = repository()->gitRepo(); - gitRef = repo.reference(r, d->mFullQualifiedName); + return gitRef; } - return gitRef; + #endif + } - namespace Internal + + namespace Data { - RefPrivate::RefPrivate(Ref* pub, RefTypes type, const Git::Reference& ref) + #if 0 + + ReferencePrivate::ReferencePrivate(Reference* pub, RefTypes type, const Git::Reference& ref) : BasePrivate( pub ) , mType( type ) , mFullQualifiedName( ref.name() ) @@ -99,36 +113,36 @@ namespace RM { } - void RefPrivate::dumpSelf(Internal::Dumper& dumper) const + void ReferencePrivate::dumpSelf(Internal::Dumper& dumper) const { dumper.addLine(QString(QStringLiteral("Ref 0x%1 [%2]")) .arg(quintptr(mPub),0,16) .arg(mName)); } - ObjTypes RefPrivate::objType() const + ObjTypes ReferencePrivate::objType() const { - return RefObject; + return ObjTypes::Reference; } - QString RefPrivate::displayName() const + QString ReferencePrivate::displayName() const { return mName; } - QString RefPrivate::objectTypeName() const + QString ReferencePrivate::objectTypeName() const { return QStringLiteral("Ref"); } - bool RefPrivate::inherits(ObjTypes type) const + bool ReferencePrivate::inherits(ObjTypes type) const { - return type == RefObject || BasePrivate::inherits(type); + return type == ObjTypes::Reference || BasePrivate::inherits(type); } - void RefPrivate::postCreation() + void ReferencePrivate::postCreation() { - RM_P(Ref); + RM_P(Reference); if (!repoEventsBlocked()) { Events::self()->refCreated(repository(), p); @@ -137,9 +151,9 @@ namespace RM BasePrivate::postCreation(); } - void RefPrivate::preTerminate() + void ReferencePrivate::preTerminate() { - RM_P(Ref); + RM_P(Reference); if ( !repoEventsBlocked() ) { Events::self()->refAboutToBeDeleted(repository(), p); @@ -148,14 +162,14 @@ namespace RM BasePrivate::preTerminate(); } - void RefPrivate::emitMoved() + void ReferencePrivate::emitMoved() { if (!repoEventsBlocked()) { Events::self()->refMoved(repository(), pub()); } } - bool RefPrivate::refreshDetails(const Git::Reference& ref) + bool ReferencePrivate::refreshDetails(const Git::Reference& ref) { Git::ObjectId id = ref.objectId(); @@ -169,7 +183,7 @@ namespace RM return true; } - bool RefPrivate::refreshSelf() + bool ReferencePrivate::refreshSelf() { Git::Result r; Repo* repo = repository(); Q_ASSERT( repo ); @@ -187,6 +201,8 @@ namespace RM return true; } + #endif + } } diff --git a/Libs/libRepoMan/Frontend/Reference.hpp b/Libs/libRepoMan/Frontend/Reference.hpp new file mode 100644 index 00000000..9e445cee --- /dev/null +++ b/Libs/libRepoMan/Frontend/Reference.hpp @@ -0,0 +1,82 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libGitWrap/ObjectId.hpp" + +#include "Base.hpp" + +namespace RM +{ + + namespace Data + { + class Reference; + } + + enum RefTypes + { + BranchType, + TagType + }; + + namespace Frontend + { + + class REPOMAN_API Reference + : public Base + { + public: + static const ObjTypes StaticObjectType = ObjTypes::Reference; + using DPtrType = Data::Reference; + using List = QList; + + protected: + Reference(Data::Reference* data); + + public: + Reference(); + + public: + GW_DEPRECATED + Reference(Base* parent, RefTypes type, const Git::Reference& ref); + + GW_DEPRECATED + Git::Reference load(Git::Result& r); + + public: + RefTypes type() const; + QString name() const; + QString fullName() const; + Git::ObjectId id() const; + QString displaySha1() const; + }; + + inline Reference::Reference() + : Base() + { + } + + GW_DEPRECATED + typedef Reference Ref; + + } + +} diff --git a/Libs/libRepoMan/Frontend/Remote.cpp b/Libs/libRepoMan/Frontend/Remote.cpp new file mode 100644 index 00000000..997ad188 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Remote.cpp @@ -0,0 +1,135 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libGitWrap/Result.hpp" + +#include "libRepoMan/Frontend/Repo.hpp" +#include "libRepoMan/Frontend/Remote.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libRepoMan/Data/Remote.hpp" + +namespace RM +{ + + namespace Frontend + { + + #if 0 + + Remote::Remote(const Git::Remote& gitObj, Base* _parent) + : Base(*new RemotePrivate(this, gitObj)) + { + RM_D(Remote); + + d->linkToParent(_parent); + } + + Git::Remote Remote::gitObject() + { + Git::Result r; + return repository()->gitRepo().remote(r, name()); + } + + QString Remote::name() const + { + RM_D(Remote); + + return d->name; + } + + CollectionNode* Remote::branches() + { + RM_D(Remote); + + + // ### We don't use this when filling up the branches, yet. + return d->getOrCreateCollection(ctBranches); + } + + #endif + + } + + namespace Data + { + + #if 0 + + RemotePrivate::RemotePrivate(Remote* _pub, const Git::Remote& _obj) + : BasePrivate(_pub) + { + name = _obj.name(); + } + + ObjTypes RemotePrivate::objType() const + { + return RemoteObject; + } + + void RemotePrivate::dumpSelf(Internal::Dumper& dumper) const + { + dumper.addLine(QString(QLatin1String("Remote %2 0x%1")) + .arg(quintptr(mPub),0,16) + .arg(name)); + } + + void RemotePrivate::postCreation() + { + if (!repoEventsBlocked()) { + Events::self()->remoteCreated(repository(), pub()); + } + + BasePrivate::postCreation(); + } + + void RemotePrivate::preTerminate() + { + if (!repoEventsBlocked()) { + Events::self()->remoteAboutToBeDeleted(repository(), pub()); + } + + BasePrivate::preTerminate(); + } + + QString RemotePrivate::displayName() const + { + return name; + } + + bool RemotePrivate::refreshSelf() + { + return true; + } + + QString RemotePrivate::objectTypeName() const + { + return QLatin1String("Remote"); + } + + bool RemotePrivate::inherits(ObjTypes type) const + { + return type == RemoteObject || BasePrivate::inherits(type); + } + + #endif + } + +} diff --git a/Libs/libRepoMan/Frontend/Remote.hpp b/Libs/libRepoMan/Frontend/Remote.hpp new file mode 100644 index 00000000..430d17b4 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Remote.hpp @@ -0,0 +1,58 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libGitWrap/Remote.hpp" + +#include "libRepoMan/Frontend/Base.hpp" + +namespace RM +{ + + namespace Data + { + class Remote; + } + + namespace Frontend + { + + class REPOMAN_API Remote : public Base + { + public: + static const ObjTypes StaticObjectType = ObjTypes::Remote; + typedef Data::Remote Private; + typedef QVector List; + + public: + Remote(const Git::Remote& gitObj, Base* parent); + + public: + GW_DEPRECATED + Git::Remote gitObject(); + QString name() const; + #if 0 // ###DEAD + CollectionNode* branches(); + #endif + }; + + } + +} diff --git a/Libs/libRepoMan/Frontend/Repo.cpp b/Libs/libRepoMan/Frontend/Repo.cpp new file mode 100644 index 00000000..8dab44e6 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Repo.cpp @@ -0,0 +1,680 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libGitWrap/Reference.hpp" +#include "libGitWrap/ObjectId.hpp" +#include "libGitWrap/RefName.hpp" +#include "libGitWrap/Submodule.hpp" + +#include "libRepoMan/RepoMan.hpp" + +#include "libRepoMan/Frontend/BaseInternal.hpp" +#include "libRepoMan/Frontend/Repo.hpp" +#include "libRepoMan/Frontend/Head.hpp" +#include "libRepoMan/Frontend/Remote.hpp" +#include "libRepoMan/Frontend/Namespace.hpp" +#include "libRepoMan/Frontend/Reference.hpp" +#include "libRepoMan/Frontend/Tag.hpp" +#include "libRepoMan/Frontend/Branch.hpp" +#include "libRepoMan/Frontend/Submodule.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libRepoMan/Data/Repo.hpp" +#include "libRepoMan/Data/Head.hpp" +#include "libRepoMan/Data/Remote.hpp" + +#include + +namespace RM +{ + + namespace Frontend + { + + Repo::Repo(const std::shared_ptr& o) + : Base(std::move(std::shared_ptr(o))) + { + } + + Repo::Repo(std::shared_ptr&& o) + : Base(std::shared_ptr(std::move(o))) + { + } + +#if 0 + Git::Repository Repo::gitRepo() + { + RM_D(Repo); + return d->gitRepo(true); + } + + Git::Repository Repo::gitLoadedRepo() + { + RM_D(Repo); + return d->gitRepo(); + } +#endif + + QString Repo::path() const + { + DPtrT d(this); + return d->path(); + } + + bool Repo::isSubModule() const + { + DPtrT d(this); + return d->mIsSubModule; + } + + bool Repo::isBare() const + { + DPtrT d(this); + return d->mIsBare; + } + + bool Repo::isLoaded() const + { + DPtrT d(this); + return d->mIsLoaded; + } + + bool Repo::isActive() const + { + DPtrT d(this); + return d && d->mIsActive; + } + + Repo Repo::parentRepository() + { + DPtrT d(this); + return d->parent()->as(); + } + + Repo::List Repo::submodules() const + { + DPtrT d(this); + return toFrontend(d->submodules()); + } + + void Repo::activated() + { + DPtrT d(this); + + Q_ASSERT(!d->mIsActive); + +#if 0 + if (d->mUnloadTimer) { + d->mUnloadTimer->stop(); + d->mUnloadTimer->deleteLater(); + d->mUnloadTimer = NULL; + } +#endif + d->mIsActive = true; + } + + void Repo::deactivated() + { + DPtrT d(this); + + Q_ASSERT(d->mIsActive); +#if 0 + Q_ASSERT(!d->mUnloadTimer); + + d->mUnloadTimer = new QTimer(this); + connect(d->mUnloadTimer, SIGNAL(timeout()), this, SLOT(unloadTimer())); + d->mUnloadTimer->setInterval(15 * 60 * 1000); // quarter of an hour + d->mUnloadTimer->start(); +#endif + + d->mIsActive = false; + } + + QString Repo::displayAlias() const + { + DPtrT d(this); + return d->mDisplayAlias; + } + + void Repo::setDisplayAlias(const QString& alias) + { +#if 0 + RM_D(Repo); + + if (d->mDisplayAlias != alias) { + d->mDisplayAlias = alias; + // ###REPOMAN Create new Event "RepoAliasChanged" + // emit aliasChanged(alias); + } +#endif + } +#if 0 + void Repo::unloadTimer() + { + RM_D(Repo); + d->unload(); + } +#endif + + void Repo::close() + { + #if 0 + RM_D(Repo); + + if (d->mIsActive) { + MacGitver::repoMan().activate(NULL); + } + + Events::self()->repositoryAboutToClose(this); + + foreach (Repo* child, submodules()) { + child->close(); + } + + d->terminateObject(); + #endif + } + + QString Repo::branchDisplay() const + { + // TODO: This method is totally wrong placed here + DPtrT d(this); + + if (d->mIsLoaded && d->mHead) { + + if (d->mHead->isDetached()) { + return QObject::tr("detached at %1" ).arg(d->mHead->detachedId().toString()); + } + + if (d->mHead->isUnborn()) { + return QObject::tr("Branch yet to be born"); + } + + return QObject::tr("%1" ).arg(d->mHead->symbolicName().mid(11)); + } + return QObject::tr("<unknown>"); + } + +#if 0 + Ref* Repo::findReference(const Git::Reference& ref) + { + RM_D(Repo); + return d->findReference(ref, false); + } + + Ref* Repo::findReference(const QString &fqrn) + { + RM_D(Repo); + return d->findReference(fqrn, false); + } + + Remote* Repo::findRemote(const Git::Remote& remote) + { + RM_D(Repo); + return d->findRemote(remote, false); + } + + Remote* Repo::findRemote(const QString& remoteName) + { + RM_D(Repo); + return d->findRemote(remoteName, false); + } + + Namespace* Repo::findNamespace(const QStringList& namespaces) + { + RM_D( Repo ); + return d->findNamespace(namespaces); + } + + Namespace* Repo::findNamespace(const QString& nsFullName) + { + RM_D( Repo ); + return d->findNamespace(nsFullName); + } + + Head* Repo::head() const + { + RM_CD(Repo); + return d->mHead; + } + + #endif + + #if 0 // ###DEAD + + /** + * @brief Get this repository's collection of branches + * + * @return A CollectionNode whose children are the branches included in this repository. + * + * Branches are references matching the regular expression `^refs/heads/.*$`. Branches may be + * scoped in which case they are subdivided into RefTreeNode objects. + * + */ + CollectionNode* Repo::branches() + { + RM_D( Repo ); + return d->getOrCreateCollection( ctBranches ); + } + + /** + * @brief Get this repository's collection of tags + * + * @return A CollectionNode whose children are the tags included in this repository. + * + * Tags are references matching the regular expression `^refs/tags/.*$`. Tags may be scoped in + * which case they are subdivided into RefTreeNode objects. + * + */ + CollectionNode* Repo::tags() + { + RM_D( Repo ); + return d->getOrCreateCollection( ctTags ); + } + + /** + * @brief Get this repository's collection of namespaces + * + * @return A CollectionNode whose children are the 1st level namespaces included in this + * repository. + * + */ + CollectionNode* Repo::namespaces() + { + RM_D(Repo); + return d->getOrCreateCollection(ctNamespaces); + } + + /** + * @brief Get this repository's collection of notes + * + * @return A CollectionNode object whose children are the notes included in this repository. + * + * Notes are refs matching the regular expression `^refs/notes/.*$`. Notes may be scoped, in + * which case they are subdivided into RefTreeNode objects. + * + */ + CollectionNode* Repo::notes() + { + RM_D(Repo); + return d->getOrCreateCollection(ctNotes); + } + + #endif + + } + + namespace Data + { + + #if 0 + RepoPrivate::RepoPrivate(Repo* pub, const Git::Repository& repo) + : BasePrivate( pub ) + { + mRepo = repo; + mHead = NULL; + mPath = mRepo.basePath(); + mIsLoaded = mRepo.isValid(); + mIsActive = false; + mIsBare = mRepo.isValid() && mRepo.isBare(); + mIsSubModule = false; + mIsInitializing = true; + mDisplayAlias = QString(); + mUnloadTimer = NULL; + + if (mPath.endsWith(L'/')) { + mPath = mPath.left(mPath.length() - 1); + } + + findAlias(); + + if (mDisplayAlias.isEmpty()) { + if (mPath.isEmpty()) { + mDisplayAlias = Repo::tr("Unknown Repository"); + } + else { + QStringList sl = mPath.split(QChar(L'/'), QString::SkipEmptyParts); + mDisplayAlias = sl.last(); + } + } + } + + RepoPrivate::~RepoPrivate() + { + RM_P(Repo); + + if (mIsLoaded) { + unload(); + } + + MacGitver::repoMan().internalClosedRepo(p); + } + + void RepoPrivate::load() + { + // ### Unimplemented: RepoPrivate::load() + Q_ASSERT(!mIsLoaded); + } + + void RepoPrivate::unload() + { + if (mIsActive) { + qDebug() << "Unloading active RepoInfo. Will deactivate it first."; + MacGitver::repoMan().activate(NULL); + } + Q_ASSERT(!mIsActive); + + if (mUnloadTimer) { + mUnloadTimer->stop(); + mUnloadTimer->deleteLater(); + mUnloadTimer = NULL; + } + + // ####REPOMAN Do we really need to send out events for Unload/Load? If yes, create + // real events for that! + mIsLoaded = false; + mRepo = Git::Repository(); + } + + + QString RepoPrivate::displayName() const + { + return mDisplayAlias; + } + + void RepoPrivate::preTerminate() + { + // Do we need to do smth? + } + + void RepoPrivate::findAlias() + { + // ### Unimplemented: RepoPrivate::findAlias() + } + + bool RepoPrivate::refreshSelf() + { + if (!mIsLoaded) { + // In case we're not loaded, just return and do nothing. + return true; + } + + if (!mHead) { + RM_P(Repo); + mHead = new Head(mRepo, p); + } + + return true; + } + + void RepoPrivate::postRefreshChildren() + { + if (!mIsLoaded) { + // In case we're not loaded, just return and do nothing. + return; + } + + Git::Result r; + Git::Remote::List remotes = mRepo.allRemotes(r); + if (r) { + foreach (const Git::Remote& remote, remotes) { + findRemote(remote, true); + } + } + + Git::ReferenceList refs = mRepo.allReferences(r); + if (r) { + foreach (Git::Reference ref, refs) { + findReference(ref, true); + } + } + + scanSubmodules(); + } + + /** + * @brief Get this object's type + * + * @return always RepoObject. + * + */ + ObjTypes RepoPrivate::objType() const + { + return RepoObject; + } + + void RepoPrivate::dumpSelf(Internal::Dumper& dumper) const + { + dumper.addLine(QString(QLatin1String("Repository 0x%1 - %02")) + .arg(quintptr(mPub),0,16) + .arg(mIsLoaded ? mRepo.name() + : QLatin1String(""))); + } + + + Ref* RepoPrivate::findReference(const Git::Reference& ref, bool create) + { + Git::RefName rn = ref.nameAnalyzer(); + return findReference(rn, ref, create); + } + + Ref* RepoPrivate::findReference(const QString& fqrn, bool create) + { + Git::RefName rn(fqrn); + return findReference(rn, Git::Reference(), create); + } + + Ref* RepoPrivate::findReference(Git::RefName& rn, Git::Reference ref, bool create) + { + Base* parent = NULL; + CollectionNode* cn = NULL; + + if (rn.isRemote() && rn.isBranch()) { + Remote* rm = findRemote(rn.remote(), create); + + if (!rm) { + return NULL; + } + + RemotePrivate* rmp = dataOf(rm); + if (!rmp) { + return NULL; + } + + parent = rmp->findRefParent(rn.scopes(), create); + } + else if (rn.isNamespaced()) { + Namespace* ns = findNamespace(rn.namespaces(), create); + + if (!ns) { + return NULL; + } + + if (rn.isBranch()) { + cn = ns->branches(); + } + else if (rn.isTag()) { + cn = ns->tags(); + } + else { + return NULL; + } + + CollectionNodePrivate* cnp = dataOf(cn); + if (!cnp) { + return NULL; + } + + parent = cnp->findRefParent(rn.scopes(), create); + } + else { + if (rn.isBranch()) { + cn = getOrCreateCollection(ctBranches); + } + else if (rn.isTag()) { + cn = getOrCreateCollection(ctTags); + } + else { + return NULL; + } + + CollectionNodePrivate* cnp = dataOf(cn); + if (!cnp) { + return NULL; + } + + parent = cnp->findRefParent(rn.scopes(), create); + } + + foreach (Ref* rmRef, parent->childObjects()) { + if (rmRef->fullName() == rn.fullName()) { + return rmRef; + } + } + + if (create) { + if ( rn.isBranch() ) { + return new Branch( parent, ref ); + } + else if( rn.isTag() ) { + return new Tag( parent, ref ); + } + else { + qDebug() << "Do not know how to deal with reference:" << rn.fullName(); + return NULL; + } + } + + return NULL; + } + + Remote* RepoPrivate::findRemote(const QString &remoteName, bool create) + { + RM_P(Repo); + + foreach (Remote* remote, p->childObjects()) { + if (remote->name() == remoteName) { + return remote; + } + } + + if (create) { + Git::Result r; + Git::Remote gr = p->gitRepo().remote(r, remoteName); + + if (r && gr.isValid()) { + Remote* remote = new Remote(gr, p); + return remote; + } + } + + return NULL; + } + + Remote* RepoPrivate::findRemote(const Git::Remote &remote, bool create) + { + RM_P( Repo ); + + if (!remote.isValid()) { + return NULL; + } + + QString remoteName = remote.name(); + foreach (Remote* rmRemote, p->childObjects()) { + if (rmRemote->name() == remoteName) { + return rmRemote; + } + } + + if (create) { + Remote* rmRemote = new Remote(remote, p); + return rmRemote; + } + + return NULL; + } + + Namespace* RepoPrivate::findNamespace(const QStringList& _namespaces, bool create) { + + Base* par = getOrCreateCollection(ctNamespaces); + Namespace* child = NULL; + + foreach (QString nsName, _namespaces) { + child = NULL; + + foreach (Namespace* ns, par->childObjects()) { + if (ns->name() == nsName) { + child = ns; + break; + } + } + + if (!child) { + if (create) { + child = new Namespace(par, nsName); + } + else { + return NULL; + } + } + + par = child; + } + + return child; + } + + Namespace* RepoPrivate::findNamespace(const QString& nsFullName, bool create) { + + QStringList nsNames = nsFullName.split(QChar(L'/')); + return findNamespace(nsNames, create); + } + + QString RepoPrivate::objectTypeName() const + { + return QLatin1String("Repo"); + } + + bool RepoPrivate::inherits(ObjTypes type) const + { + return type == RepoObject || BasePrivate::inherits(type); + } + + Repo* RepoPrivate::searchRepository() + { + return static_cast(mPub); + } + + Git::Repository RepoPrivate::gitRepo(bool doLoad) + { + if (!mIsLoaded && doLoad) { + load(); + } + + return mRepo; + } + + #endif + + } + +} + diff --git a/Libs/libRepoMan/Frontend/Repo.hpp b/Libs/libRepoMan/Frontend/Repo.hpp new file mode 100644 index 00000000..07629104 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Repo.hpp @@ -0,0 +1,116 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libGitWrap/Repository.hpp" + +#include "libRepoMan/Frontend/Base.hpp" + +namespace RM +{ + + class RepoMan; + class Head; + + namespace Data + { + class Repo; + } + + namespace Frontend + { + + class REPOMAN_API Repo + : public Base + { + friend class RepoMan; + public: + static const ObjTypes StaticObjectType = ObjTypes::Repo; + typedef Data::Repo DPtrType; + typedef QVector List; + + public: + Repo() = default; + Repo(const std::shared_ptr& o); + Repo(std::shared_ptr&& o); + ~Repo() = default; + + bool operator==(const Repo& other) const; + + public: + GW_DEPRECATED Git::Repository gitRepo(); + GW_DEPRECATED Git::Repository gitLoadedRepo(); + + bool isSubModule() const; + bool isBare() const; + bool isLoaded() const; + bool isActive() const; + bool isInitializing() const; + + Repo parentRepository(); + List submodules() const; + + QString path() const; + + QString displayAlias() const; + void setDisplayAlias( const QString& alias ); + + QString branchDisplay() const; + + void close(); + + GW_DEPRECATED + Reference findReference( const Git::Reference& ref); + Reference findReference( const QString& fqrn); + + GW_DEPRECATED + Remote findRemote( const Git::Remote& remote); + Remote findRemote( const QString& remoteName); + + Namespace findNamespace( const QStringList& namespaces); + Namespace findNamespace( const QString& nsFullName); + + #if 0 // ###DEAD + CollectionNode* branches(); + CollectionNode* namespaces(); + CollectionNode* notes(); + CollectionNode* tags(); + Head* head() const; + #endif + + private: + void activated(); + void deactivated(); + + #if 0 // ###DEAD + private slots: + void unloadTimer(); + #endif + }; + + + inline bool Repo::operator==(const Repo& other) const + { + return Base::operator==(other); + } + + } + +} diff --git a/Libs/libRepoMan/Frontend/Submodule.cpp b/Libs/libRepoMan/Frontend/Submodule.cpp new file mode 100644 index 00000000..bdabdab1 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Submodule.cpp @@ -0,0 +1,101 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Data/Submodule.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +namespace RM +{ + + namespace Frontend + { + + #if 0 + Submodule::Submodule(const Git::Repository& repo, Repo* parent) + : Repo( *new RM::Data::Submodule( this, repo ) ) + { + RM_D(Submodule); + + d->mIsSubModule = true; + + setDisplayAlias( repo.name() ); + + d->linkToParent( parent ); + d->refresh(); + + d->mIsInitializing = false; + } + #endif + + } + + namespace Data + { + #if 0 + + SubmodulePrivate::SubmodulePrivate(Submodule* pub, const Git::Repository& repo) + : RepoPrivate( pub, repo ) + { + } + + ObjTypes SubmodulePrivate::objType() const + { + return SubmoduleObject; + } + + void SubmodulePrivate::dumpSelf(Dumper& dumper) const + { + dumper.addLine(QString(QLatin1String("Submodule 0x%1")) + .arg(quintptr(mPub),0,16)); + } + + void SubmodulePrivate::postCreation() + { + if (!repoEventsBlocked()) { + Events::self()->submoduleCreated(repository(), pub()); + } + + RepoPrivate::postCreation(); + } + + void SubmodulePrivate::preTerminate() + { + if (!repoEventsBlocked()) { + Events::self()->submoduleAboutToBeDeleted(repository(), pub()); + } + + RepoPrivate::preTerminate(); + } + + QString SubmodulePrivate::objectTypeName() const + { + return QLatin1String("Submodule"); + } + + bool SubmodulePrivate::inherits(ObjTypes type) const + { + return type == SubmoduleObject || RepoPrivate::inherits(type); + } + + #endif + + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/Private/TagPrivate.hpp b/Libs/libRepoMan/Frontend/Submodule.hpp similarity index 70% rename from Libs/libMacGitverCore/RepoMan/Private/TagPrivate.hpp rename to Libs/libRepoMan/Frontend/Submodule.hpp index 896da3b1..ef3ee8cd 100644 --- a/Libs/libMacGitverCore/RepoMan/Private/TagPrivate.hpp +++ b/Libs/libRepoMan/Frontend/Submodule.hpp @@ -19,28 +19,28 @@ #pragma once -#include "RepoMan/Private/RefPrivate.hpp" - -#include "RepoMan/Tag.hpp" +#include "libRepoMan/Frontend/Repo.hpp" namespace RM { - namespace Internal + namespace Frontend { - class TagPrivate : public RefPrivate + class REPOMAN_API Submodule : public Repo { public: - TagPrivate(Tag* pub, const Git::Reference& _ref); + static const ObjTypes StaticObjectType = ObjTypes::Submodule; + + public: + Submodule(const Git::Repository& repo, Repo* parent); public: + + private: ObjTypes objType() const; - void postCreation(); void preTerminate(); - void dumpSelf(Dumper& dumper) const; - QString objectTypeName() const; - bool inherits(ObjTypes type) const; + void dumpSelf(Internal::Dumper& dumper) const; }; } diff --git a/Libs/libRepoMan/Frontend/Tag.cpp b/Libs/libRepoMan/Frontend/Tag.cpp new file mode 100644 index 00000000..d977d77e --- /dev/null +++ b/Libs/libRepoMan/Frontend/Tag.cpp @@ -0,0 +1,96 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Frontend/Tag.hpp" + +#include "libRepoMan/Private/Dumper.hpp" + +#include "libRepoMan/Data/Tag.hpp" + +namespace RM +{ + + namespace Frontend + { + + #if 0 + Tag::Tag(Base* _parent, const Git::Reference& _ref) + : Ref(*new TagPrivate(this, _ref)) + { + RM_D(Tag); + d->linkToParent(_parent); + } + + #endif + + } + + namespace Data + { + + #if 0 + + TagPrivate::TagPrivate(Tag* _pub, const Git::Reference& _ref) + : RefPrivate(_pub, TagType, _ref) + { + } + + ObjTypes TagPrivate::objType() const + { + return TagObject; + } + + void TagPrivate::postCreation() + { + if (!repoEventsBlocked()) { + Events::self()->tagCreated(repository(), pub()); + } + + RefPrivate::postCreation(); + } + + void TagPrivate::preTerminate() + { + if (!repoEventsBlocked()) { + Events::self()->tagAboutToBeDeleted(repository(), pub()); + } + RefPrivate::preTerminate(); + } + + void TagPrivate::dumpSelf(Internal::Dumper& dumper) const + { + dumper.addLine(QString(QLatin1String("Tag 0x%1 - %2")) + .arg(quintptr(mPub),0,16) + .arg(mName)); + } + + QString TagPrivate::objectTypeName() const + { + return QLatin1String("Tag"); + } + + bool TagPrivate::inherits(ObjTypes type) const + { + return type == TagObject || RefPrivate::inherits(type); + } + #endif + + } + +} diff --git a/Libs/libRepoMan/Frontend/Tag.hpp b/Libs/libRepoMan/Frontend/Tag.hpp new file mode 100644 index 00000000..ae0a85d5 --- /dev/null +++ b/Libs/libRepoMan/Frontend/Tag.hpp @@ -0,0 +1,52 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Frontend/Reference.hpp" + +namespace RM +{ + + namespace Frontend + { + + class REPOMAN_API Tag + : public Reference + { + public: + static const ObjTypes StaticObjectType = ObjTypes::Tag; + typedef QVector List; + + public: + Tag(Base* _parent, const Git::Reference& _ref); + + public: + + private: + ObjTypes objType() const; + void preTerminate(); + void dumpSelf(Internal::Dumper& dumper) const; + + private: + }; + + } + +} diff --git a/Libs/libMacGitverCore/RepoMan/Private/Dumper.cpp b/Libs/libRepoMan/Private/Dumper.cpp similarity index 100% rename from Libs/libMacGitverCore/RepoMan/Private/Dumper.cpp rename to Libs/libRepoMan/Private/Dumper.cpp diff --git a/Libs/libMacGitverCore/RepoMan/Private/Dumper.hpp b/Libs/libRepoMan/Private/Dumper.hpp similarity index 100% rename from Libs/libMacGitverCore/RepoMan/Private/Dumper.hpp rename to Libs/libRepoMan/Private/Dumper.hpp diff --git a/Libs/libMacGitverCore/RepoMan/Private/RepoManActions.hid b/Libs/libRepoMan/Private/RepoManActions.hid similarity index 100% rename from Libs/libMacGitverCore/RepoMan/Private/RepoManActions.hid rename to Libs/libRepoMan/Private/RepoManActions.hid diff --git a/Libs/libMacGitverCore/RepoMan/RepoMan.cpp b/Libs/libRepoMan/RepoMan.cpp similarity index 68% rename from Libs/libMacGitverCore/RepoMan/RepoMan.cpp rename to Libs/libRepoMan/RepoMan.cpp index 279a9612..479c0e65 100644 --- a/Libs/libMacGitverCore/RepoMan/RepoMan.cpp +++ b/Libs/libRepoMan/RepoMan.cpp @@ -17,25 +17,28 @@ * */ -#include "libMacGitverCore/App/MacGitver.hpp" +#include "libRepoMan/RepoMan.hpp" -#include "RepoMan/RepoMan.hpp" -#include "RepoMan/CollectionNode.hpp" -#include "RepoMan/Events.hpp" +#include "libRepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/Dumper.hpp" -#include "RepoMan/Private/RepoManPrivate.hpp" -#include "RepoMan/Private/RepoPrivate.hpp" +#include "libRepoMan/Backend/ServiceRunner.hpp" + +#include "libRepoMan/Services/OpenRepository.hpp" +#include "libRepoMan/Services/RefreshRepository.hpp" + +#include "libRepoMan/Data/RepoMan.hpp" +#include "libRepoMan/Data/Repo.hpp" + +#include "libLogger/Manager.hpp" #include "libBlueSky/Application.hpp" #include +#include namespace RM { - using namespace Internal; - /** * @class RepoMan * @brief Manages the open / active repositories @@ -48,14 +51,11 @@ namespace RM * */ RepoMan::RepoMan() - : Base(*new RepoManPrivate(this)) { - Events::addReceiver(this); - connect(BlueSky::Application::instance(), - SIGNAL(activeModeChanged(BlueSky::Mode*)), + &BlueSky::Application::activeModeChanged, this, - SLOT(reactivateWorkaround())); + &RepoMan::reactivateWorkaround); } /** @@ -67,7 +67,6 @@ namespace RM RepoMan::~RepoMan() { closeAll(); - Events::delReceiver(this); } RepoMan& RepoMan::instance() @@ -94,8 +93,7 @@ namespace RM */ void RepoMan::open(const QString& path) { - // ### REPOMAN TODO - qDebug() << "RepoMan::Open is currently not implemented."; + Backend::perform(new Services::OpenRepository(path)); } /** @@ -104,24 +102,29 @@ namespace RM */ void RepoMan::closeAll() { + #if 0 // ###DEAD RM_D(RepoMan); foreach(Repo* repo, d->repos) { repo->close(); } + #endif } void RepoMan::reactivateWorkaround() { + #if 0 // ###DEAD RM_D(RepoMan); if (d->activeRepo) { Events::self()->repositoryDeactivated(d->activeRepo); Events::self()->repositoryActivated(d->activeRepo); } + #endif } - void RepoMan::activate(Repo* repository) + void RepoMan::activate(const Frontend::Repo& repository) { + #if 0 // ###DEAD RM_D(RepoMan); if(repository != d->activeRepo) { @@ -144,8 +147,10 @@ namespace RM emit hasActiveRepositoryChanged(d->activeRepo != NULL); } } + #endif } + #if 0 // ###DEAD void RepoMan::internalClosedRepo(Repo* repository) { RM_D(RepoMan); @@ -168,32 +173,42 @@ namespace RM } } } + #endif - Repo* RepoMan::activeRepository() + Frontend::Repo RepoMan::activeRepository() { + #if 0 // ###DEAD RM_D(RepoMan); return d->activeRepo; + #else + return Frontend::Repo(); + #endif } - Repo::List RepoMan::repositories() const + Frontend::Repo::List RepoMan::repositories() const { + #if 0 // ###DEAD RM_CD(RepoMan); return d->repos; + #else + return Frontend::Repo::List(); + #endif + } + + void RepoMan::refresh(RefreshTypes what) + { + Log::Manager().addMessage(trUtf8("Refreshing git repositories...")); + Backend::perform(new Services::RefreshRepository(activeRepository())); } + #if 0 // ###DEAD //-- RepoManPrivate ---------------------------------------------------------------------------- RepoManPrivate::RepoManPrivate(RepoMan* _pub) : BasePrivate(_pub) , activeRepo(NULL) - , refresher(NULL) { setupActions(_pub); - - // only start the auto refresher if we're running a GUI - if (MacGitver::self().isRunningGui()) { - refresher = new AutoRefresher(_pub); - } } bool RepoManPrivate::refreshSelf() @@ -203,7 +218,7 @@ namespace RM ObjTypes RepoManPrivate::objType() const { - return RepoManagerObject; + return ObjTypes::RepoManager; } void RepoManPrivate::dumpSelf(Internal::Dumper& dumper) const @@ -216,48 +231,19 @@ namespace RM // Do we need to do smth? } - QString RepoManPrivate::displayName() const - { - return QStringLiteral("RepoMan"); - } - - QString RepoManPrivate::objectTypeName() const - { - return QStringLiteral("RepoMan"); - } - Heaven::Menu* RepoManPrivate::contextMenuFor(Base* object) { switch (object->objType()) { - - case BranchObject: return menuCtxBranch; - case TagObject: return menuCtxTag; - case RepoObject: return menuCtxRepo; - case SubmoduleObject: return menuCtxSubmodule; - case NamespaceObject: return menuCtxNamespace; - case RefLogObject: return menuCtxRefLog; - case RemoteObject: return menuCtxRemote; - - //case RefObject: return menuCtxRef; - //case RefTreeNodeObject: return menuCtxRefTreeNode; - - case CollectionNodeObject: - switch (static_cast(object)->collectionType()) { - - case ctBranches: return menuCtxBranches; - case ctTags: return menuCtxTags; - case ctNotes: return menuCtxNotes; - case ctNamespaces: return menuCtxNamespaces; - - default: break; - } - break; - - default: - break; + case ObjTypes::Branch: return menuCtxBranch; + case ObjTypes::Tag: return menuCtxTag; + case ObjTypes::Repo: return menuCtxRepo; + case ObjTypes::Submodule: return menuCtxSubmodule; + case ObjTypes::Namespace: return menuCtxNamespace; + case ObjTypes::RefLog: return menuCtxRefLog; + case ObjTypes::Remote: return menuCtxRemote; + default: return nullptr; } - - return NULL; } + #endif } diff --git a/Libs/libRepoMan/RepoMan.hpp b/Libs/libRepoMan/RepoMan.hpp new file mode 100644 index 00000000..9b9ce51d --- /dev/null +++ b/Libs/libRepoMan/RepoMan.hpp @@ -0,0 +1,111 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Frontend/Repo.hpp" + +#include "libRepoMan/Events/Event.hpp" +#include "libRepoMan/Events/Compat.hpp" + +#include + +namespace RM +{ + + enum class RefreshTypes + { + Repositories, + Indicies, + Worktrees + }; + + namespace Frontend { class Branch; } + + class REPOMAN_API RepoMan + : public QObject + , private CompatEventsInterface + { + Q_OBJECT + private: + RepoMan(); + public: + ~RepoMan(); + + public: + void refresh(RefreshTypes what); + void open(const QString& path); + + void closeAll(); + + Frontend::Repo activeRepository(); + void activate(const Frontend::Repo& repository); + + Frontend::Repo::List repositories() const; + + public: + static RepoMan& instance(); + void terminate(); + + private slots: + void reactivateWorkaround(); + + signals: + void firstRepositoryOpened(); + void lastRepositoryClosed(); + void repositoryClosed(); + void hasActiveRepositoryChanged(bool hasActiveRepo); + + signals: + void repositoryOpened(const RM::Frontend::Repo& repo); + void repositoryAboutToClose(const RM::Frontend::Repo& repo); + void repositoryActivated(const RM::Frontend::Repo& repo); + void repositoryDeactivated(const RM::Frontend::Repo& repo); + void objectCreated(const RM::Frontend::Base& object); + void objectAboutToBeDeleted(const RM::Frontend::Base& object); + void refTreeNodeCreated(const RM::Frontend::RefTreeNode& node); + void refTreeNodeAboutToBeDeleted(const RM::Frontend::RefTreeNode& node); + void refCreated(const RM::Frontend::Reference& ref); + void refAboutToBeDeleted(const RM::Frontend::Reference& ref); + void refMoved(const RM::Frontend::Reference& ref); + void refHeadDetached(const RM::Frontend::Reference& ref); + void tagCreated(const RM::Frontend::Tag& tag); + void tagAboutToBeDeleted(const RM::Frontend::Tag& tag); + void branchCreated(const RM::Frontend::Branch& branch); + void branchAboutToBeDeleted(const RM::Frontend::Branch& branch); + void branchMoved(const RM::Frontend::Branch& branch); + void branchUpstreamChanged(const RM::Frontend::Branch& branch); + void namespaceCreated(const RM::Frontend::Namespace& nameSpace); + void namespaceAboutToBeDeleted(const RM::Frontend::Namespace& nameSpace); + void refLogChanged(const RM::Frontend::RefLog& reflog); + void refLogNewEntry(const RM::Frontend::RefLog& reflog); + void stageCreated(const RM::Frontend::Reference& ref); + void stageAboutToBeDeleted(const RM::Frontend::Reference& ref); + void remoteCreated(const RM::Frontend::Remote& remote); + void remoteAboutToBeDeleted(const RM::Frontend::Remote& remote); + void remoteModified(const RM::Frontend::Remote& remote); + void submoduleCreated(const RM::Frontend::Submodule& submodule); + void submoduleAboutToBeDeleted(const RM::Frontend::Submodule& submodule); + void submoduleMoved(const RM::Frontend::Submodule& submodule); + void repositoryStateChanged(const RM::Frontend::Repo& repo); + void indexUpdated(); + void workTreeUpdated(); + }; + +} diff --git a/Libs/libRepoMan/Services/OpenRepository.cpp b/Libs/libRepoMan/Services/OpenRepository.cpp new file mode 100644 index 00000000..b163a6b1 --- /dev/null +++ b/Libs/libRepoMan/Services/OpenRepository.cpp @@ -0,0 +1,44 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Data/Repo.hpp" +#include "libRepoMan/Services/OpenRepository.hpp" + +#include "libGitWrap/Repository.hpp" + +namespace RM { namespace Services { + +OpenRepository::OpenRepository(const QString& path) + : mPath(path) +{ +} + +void OpenRepository::run() +{ + Git::Result res; + Git::Repository gitRepo = Git::Repository::open(res, mPath); + if (!res) { + logGitError(res); + } + + Data::Repo::SPtr repoData; + repoData.make_shared(gitRepo); +} + +} } diff --git a/Libs/libMacGitverCore/RepoMan/RefLog.hpp b/Libs/libRepoMan/Services/OpenRepository.hpp similarity index 71% rename from Libs/libMacGitverCore/RepoMan/RefLog.hpp rename to Libs/libRepoMan/Services/OpenRepository.hpp index 45bcab0f..85b44f6d 100644 --- a/Libs/libMacGitverCore/RepoMan/RefLog.hpp +++ b/Libs/libRepoMan/Services/OpenRepository.hpp @@ -19,24 +19,22 @@ #pragma once -#include "Base.hpp" +#include "libRepoMan/Backend/AbstractService.hpp" -namespace RM -{ +namespace RM { namespace Services { - namespace Internal - { - class RefLogPrivate; - } +class OpenRepository + : public Backend::AbstractService +{ + Q_OBJECT +public: + OpenRepository(const QString& path); - class MGV_CORE_API RefLog : public Base - { - public: - enum { StaticObjectType = RefLogObject }; - typedef Internal::RefLogPrivate Private; +private: + void run(); - public: - RefLog(Base* _parent); - }; +private: + QString mPath; +}; -} +} } diff --git a/Libs/libRepoMan/Services/RefreshRepository.cpp b/Libs/libRepoMan/Services/RefreshRepository.cpp new file mode 100644 index 00000000..1c6708ca --- /dev/null +++ b/Libs/libRepoMan/Services/RefreshRepository.cpp @@ -0,0 +1,100 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#include "libRepoMan/Backend/RepoMan.hpp" + +#include "libRepoMan/Backend/RepoLocker.hpp" +#include "libRepoMan/Services/RefreshRepository.hpp" + +#include "libGitWrap/Submodule.hpp" + +#include + +namespace RM { namespace Services { + +RefreshRepository::RefreshRepository(const Frontend::Repo& repo) + : mRepo() +{ + +} + +RefreshRepository::RefreshRepository(const Data::Repo::SPtr& repo) + : mRepo(repo) +{ +} + +void RefreshRepository::run() +{ + Backend::RepoLocker lock(mRepo); + + mGitRepo = mRepo->gitRepo(false); + if (!mGitRepo.isValid()) { + return; + } + + scanSubmodules(); +} + + +void RefreshRepository::scanSubmodules() +{ + Git::Result r; + Git::Submodule::List subs = mGitRepo.submodules(r); + if (!r) { + return; + } + + Data::Repo::SList oldSubmodules = Data::sharedFromWeakList(mRepo->submodules()); + + foreach (Git::Submodule sub, subs) { + Git::Result child; + + Git::Repository subRepo = sub.subRepository(child); + if (!child) { + // If we cannot load the repository, keep it in list of submodules to remove. + continue; + } + Q_ASSERT(subRepo.isValid()); + + QString path = subRepo.workTreePath(); + + if (path.endsWith(L'/')) { + path = path.left(path.length() - 1); + } + + auto it = std::find(oldSubmodules.begin(), oldSubmodules.end(), + mRepo->repoByPath(path, true)); + if (it != oldSubmodules.end()) { + oldSubmodules.erase(it); + } + else { + // ###REPOMAN + qDebug() << "Existing Submodule does not exist in data structure"; + // subInfo = new Submodule(subRepo, p); + } + } + + foreach (Data::Repo::WPtr repo, oldSubmodules) { + // ###REPOMAN + Q_UNUSED(repo); + // dataOf(repo)->terminateObject(); + } +} + +} } diff --git a/Libs/libRepoMan/Services/RefreshRepository.hpp b/Libs/libRepoMan/Services/RefreshRepository.hpp new file mode 100644 index 00000000..c2495fd6 --- /dev/null +++ b/Libs/libRepoMan/Services/RefreshRepository.hpp @@ -0,0 +1,46 @@ +/* + * MacGitver + * Copyright (C) 2012-2015 The MacGitver-Developers + * + * (C) Sascha Cunz + * (C) Cunz RaD Ltd. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License (Version 2) as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if + * not, see . + * + */ + +#pragma once + +#include "libRepoMan/Backend/AbstractService.hpp" +#include "libRepoMan/Data/Repo.hpp" + +namespace RM { namespace Services { + +class RefreshRepository + : public Backend::AbstractService +{ + Q_OBJECT +public: + RefreshRepository(const Frontend::Repo& repo); + RefreshRepository(const Data::Repo::SPtr& repo); + +private: + void run(); + +private: + void scanSubmodules(); + +private: + Data::Repo::SPtr mRepo; + Git::Repository mGitRepo; +}; + +} } diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt index 7d30339a..e3308327 100644 --- a/Modules/CMakeLists.txt +++ b/Modules/CMakeLists.txt @@ -7,12 +7,12 @@ INCLUDE_DIRECTORIES( ${HEAVEN_INCLUDE_DIRS} ) -ADD_SUBDIRECTORY(History) +#ADD_SUBDIRECTORY(History) ADD_SUBDIRECTORY(GitConfig) -ADD_SUBDIRECTORY(RefsViews) +#ADD_SUBDIRECTORY(RefsViews) ADD_SUBDIRECTORY(Repository) -ADD_SUBDIRECTORY(Remotes) +#ADD_SUBDIRECTORY(Remotes) ADD_SUBDIRECTORY(Welcome) -ADD_SUBDIRECTORY(WorkingTree) +#ADD_SUBDIRECTORY(WorkingTree) ADD_SUBDIRECTORY(Logging) ADD_SUBDIRECTORY(RepoManLogger) diff --git a/Modules/GitConfig/GitConfigModule.cpp b/Modules/GitConfig/GitConfigModule.cpp index 3b4edb6a..1afcf167 100644 --- a/Modules/GitConfig/GitConfigModule.cpp +++ b/Modules/GitConfig/GitConfigModule.cpp @@ -18,8 +18,7 @@ #include #include "libMacGitverCore/App/MacGitver.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/Repo.hpp" +#include "libRepoMan/RepoMan.hpp" #include "GitConfigModule.h" #include "GitConfigDialog.h" @@ -40,10 +39,13 @@ void GitConfigModule::deinitialize() void GitConfigModule::onToolsGitConfig() { + RM::Frontend::Repo repo(RM::RepoMan::instance().activeRepository()); + + #if 0 // ###REPOMAN Git::Repository gitRepo; - RM::Repo* repo = MacGitver::repoMan().activeRepository(); if (repo) { gitRepo = repo->gitRepo(); } GitConfigDialog( gitRepo ).exec(); + #endif } diff --git a/Modules/History/HistoryList.cpp b/Modules/History/HistoryList.cpp index 82152e44..0b7f712a 100644 --- a/Modules/History/HistoryList.cpp +++ b/Modules/History/HistoryList.cpp @@ -16,7 +16,7 @@ #include "libMacGitverCore/App/MacGitver.hpp" #include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/Repo.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Repo.hpp" #include "libMacGitverCore/Widgets/HeaderView.h" #include "CreateBranchDialog.h" @@ -128,6 +128,7 @@ QModelIndex HistoryList::deeplyMapToSource( QModelIndex current ) const void HistoryList::onCheckout() { + #if 0 // ### REPOMAN Heaven::Action* action = qobject_cast< Heaven::Action* >( sender() ); if ( !action ) return; @@ -162,10 +163,12 @@ void HistoryList::onCheckout() trUtf8("Checkout of commit failed. Git message:\n%1").arg(r.errorText())); return; } + #endif } void HistoryList::checkout(Git::Result& result, const Git::Reference& ref) { + #if 0 // ### REPOMAN GW_CHECK_RESULT(result, void()); Git::CheckoutReferenceOperation* op = new Git::CheckoutReferenceOperation( ref ); @@ -181,10 +184,12 @@ void HistoryList::checkout(Git::Result& result, const Git::Reference& ref) .arg( ref.shorthand() ) .arg( result.errorText() ) ); } + #endif } void HistoryList::onCreateBranch() { + #if 0 // ### REPOMAN Heaven::Action* action = qobject_cast< Heaven::Action* >( sender() ); if ( !action ) return; @@ -220,10 +225,12 @@ void HistoryList::onCreateBranch() { checkout( r, branch ); } + #endif } void HistoryList::onCreateTag() { + #if 0 // ### REPOMAN Heaven::Action* action = qobject_cast< Heaven::Action* >( sender() ); if ( !action ) return; @@ -253,10 +260,12 @@ void HistoryList::onCreateTag() trUtf8("Failed to create tag. Git message:\n%1").arg(r.errorText()) ); return; } + #endif } void HistoryList::onShowHEAD() { + #if 0 // ### REPOMAN Git::Result r; Git::Repository repo = MacGitver::repoMan().activeRepository()->gitRepo(); @@ -280,5 +289,6 @@ void HistoryList::onShowHEAD() "Important Note: This is a feature preview!\n\n" "Please make sure the HEAD commit is at least once visible!" ) ); } + #endif } diff --git a/Modules/History/HistoryModel.cpp b/Modules/History/HistoryModel.cpp index 5c964087..a655d851 100644 --- a/Modules/History/HistoryModel.cpp +++ b/Modules/History/HistoryModel.cpp @@ -22,7 +22,7 @@ #include "libMacGitverCore/App/MacGitver.hpp" #include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/Ref.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Reference.hpp" #include "libGitWrap/Reference.hpp" @@ -40,7 +40,7 @@ HistoryModel::HistoryModel( const Git::Repository& repo, QObject* parent ) mDisplays = 0; - RM::RepoMan &rm = MacGitver::repoMan(); + RM::RepoMan &rm = RM::RepoMan::instance(); connect(&rm, &RM::RepoMan::refCreated, this, &HistoryModel::onRefCreated); connect(&rm, &RM::RepoMan::refAboutToBeDeleted, this, &HistoryModel::onRefDestroyed); connect(&rm, &RM::RepoMan::refMoved, this, &HistoryModel::onRefMoved); @@ -229,35 +229,41 @@ void HistoryModel::afterAppend() endInsertRows(); } -void HistoryModel::onRefCreated(RM::Repo* repo, RM::Ref* ref) +void HistoryModel::onRefCreated(const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref) { Q_UNUSED( ref ) + #if 0 // ###REPOMAN if ( !repo || (repo->gitLoadedRepo() != mRepo) ) { return; } + #endif scanInlineReferences(); } -void HistoryModel::onRefDestroyed(RM::Repo* repo, RM::Ref* ref) +void HistoryModel::onRefDestroyed(const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref) { Q_UNUSED( ref ) + #if 0 // ###REPOMAN if ( !repo || (repo->gitLoadedRepo() != mRepo) ) { return; } + #endif scanInlineReferences(); } -void HistoryModel::onRefMoved(RM::Repo* repo, RM::Ref* ref) +void HistoryModel::onRefMoved(const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref) { Q_UNUSED( ref ); + #if 0 // ###REPOMAN if ( !repo || (repo->gitLoadedRepo() != mRepo) ) { return; } + #endif scanInlineReferences(); } diff --git a/Modules/History/HistoryModel.h b/Modules/History/HistoryModel.h index 39e4875d..606f1ae8 100644 --- a/Modules/History/HistoryModel.h +++ b/Modules/History/HistoryModel.h @@ -30,8 +30,11 @@ namespace RM { - class Ref; - class Repo; + namespace Frontend + { + class Reference; + class Repo; + } } class HistoryModel : public QAbstractTableModel @@ -114,9 +117,9 @@ private slots: void beforeAppend(); void afterAppend(); - void onRefCreated(RM::Repo* repo, RM::Ref* ref); - void onRefDestroyed(RM::Repo* repo, RM::Ref* ref); - void onRefMoved(RM::Repo*repo, RM::Ref*ref); + void onRefCreated (const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref); + void onRefDestroyed(const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref); + void onRefMoved (const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref); private: InlineRefDisplays mDisplays; diff --git a/Modules/History/HistoryView.cpp b/Modules/History/HistoryView.cpp index cd656611..fdd981fe 100644 --- a/Modules/History/HistoryView.cpp +++ b/Modules/History/HistoryView.cpp @@ -31,7 +31,7 @@ #include "libMacGitverCore/App/MacGitver.hpp" #include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/Repo.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Repo.hpp" #include "HistoryView.h" #include "HistoryEntry.h" @@ -73,13 +73,14 @@ HistoryView::HistoryView() this, &HistoryView::repoActivated); } -void HistoryView::repoActivated(RM::Repo* repo) +void HistoryView::repoActivated(const RM::Frontend::Repo& repo) { if (mRepo != repo) { mRepo = repo; - Git::Repository repo = mRepo->gitRepo(); + #if 0 // ###REPOMAN + Git::Repository repo = mRepo.gitRepo(); if (mModel) { mList->setModel(NULL); @@ -104,6 +105,7 @@ void HistoryView::repoActivated(RM::Repo* repo) mModel->buildHistory(); mList->setModel(mModel); } + #endif } } diff --git a/Modules/History/HistoryView.h b/Modules/History/HistoryView.h index 10c64071..efd0239f 100644 --- a/Modules/History/HistoryView.h +++ b/Modules/History/HistoryView.h @@ -33,10 +33,7 @@ class QToolBar; #include "HistoryModel.h" -namespace RM -{ - class Repo; -} +#include "libMacGitverCore/RepoMan/Frontend/Repo.hpp" class HistoryDetails; class HistoryList; @@ -53,7 +50,7 @@ class HistoryView : public BlueSky::View, HistoryView(); private slots: - void repoActivated(RM::Repo* repo); + void repoActivated(const RM::Frontend::Repo& repo); void currentCommitChanged(const Git::ObjectId& sha1); void onChangeShowLocalBranches(bool checked); @@ -78,7 +75,7 @@ private slots: HistoryList* mList; HistoryDetails* mDetails; HistoryDiff* mDiff; - RM::Repo* mRepo; + RM::Frontend::Repo mRepo; }; #endif diff --git a/Modules/Logging/LoggingMode.cpp b/Modules/Logging/LoggingMode.cpp index 55cdab78..e00499fa 100644 --- a/Modules/Logging/LoggingMode.cpp +++ b/Modules/Logging/LoggingMode.cpp @@ -20,8 +20,7 @@ #include #include "libMacGitverCore/App/MacGitver.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" - +#include "libRepoMan/RepoMan.hpp" #include "LoggingMode.hpp" LoggingMode::LoggingMode(QObject *parent) diff --git a/Modules/RefsViews/Branches/BranchesModel.cpp b/Modules/RefsViews/Branches/BranchesModel.cpp index c94576e1..f6af1f42 100644 --- a/Modules/RefsViews/Branches/BranchesModel.cpp +++ b/Modules/RefsViews/Branches/BranchesModel.cpp @@ -16,21 +16,19 @@ * */ -#include -#include +#include "BranchesModel.hpp" #include "libMacGitverCore/App/MacGitver.hpp" #include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/Ref.hpp" -#include "libMacGitverCore/RepoMan/RefTreeNode.hpp" -#include "libMacGitverCore/RepoMan/Branch.hpp" -#include "libMacGitverCore/RepoMan/Remote.hpp" -#include "libMacGitverCore/RepoMan/CollectionNode.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Reference.hpp" +#include "libMacGitverCore/RepoMan/Frontend/RefTreeNode.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Branch.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Remote.hpp" #include "libGitWrap/Result.hpp" -#include "BranchesModel.hpp" - +#include +#include BranchesModel::BranchesModel( BranchesViewData* parent ) : QAbstractItemModel( parent ) @@ -40,7 +38,7 @@ BranchesModel::BranchesModel( BranchesViewData* parent ) , mHeaderRemote( NULL ) , mHeaderTags( NULL ) { - RM::RepoMan& rm = MacGitver::repoMan(); + RM::RepoMan& rm = RM::RepoMan::instance(); connect(&rm, &RM::RepoMan::refCreated, this, &BranchesModel::onRefCreated); @@ -76,15 +74,14 @@ QModelIndex BranchesModel::itemToIndex(RefItem* item) const return createIndex( row, 0, item ); } -QModelIndex BranchesModel::objectToIndex(RM::Base* obj) const +QModelIndex BranchesModel::objectToIndex(const RM::Frontend::Base& obj) const { return itemToIndex(mObjToItems.value(obj, NULL)); } -int BranchesModel::rowCount( const QModelIndex& parent ) const +int BranchesModel::rowCount(const QModelIndex& parent) const { - if( parent.column() > 0 ) - { + if (parent.column() > 0) { return 0; } @@ -92,17 +89,19 @@ int BranchesModel::rowCount( const QModelIndex& parent ) const return parentItem->children.count(); } -int BranchesModel::columnCount( const QModelIndex& parent ) const +int BranchesModel::columnCount(const QModelIndex& parent) const { return 1; } -QVariant BranchesModel::data( const QModelIndex& index, int role ) const +QVariant BranchesModel::data(const QModelIndex& index, int role) const { RefItem* item = indexToItem(index); + if (index.column() != 0) { return QVariant(); } + return item ? item->data(role) : QVariant(); } @@ -178,15 +177,15 @@ RefItem* BranchesModel::link(bool notify, RefItem* it) return it; } -RefItem* BranchesModel::createBranchItem(bool notify, RefItem* parent, RM::Branch* obj) +RefItem* BranchesModel::createBranchItem(bool notify, RefItem* parent, const RM::Frontend::Branch& obj) { - if (obj->name() == QStringLiteral("HEAD")) { - return NULL; + if (obj.name() == QStringLiteral("HEAD")) { + return nullptr; } - if (!parent && obj->parentObject()->objType() != RM::CollectionNodeObject) { - parent = insertObject(notify, obj->parentObject()); - return NULL; + if (!parent /* && obj.parent().objType() != RM::ObjTypes::CollectionNode */) { // ###REPOMAN + parent = insertObject(notify, obj.parent()); + return nullptr; } if (!parent) { @@ -196,10 +195,10 @@ RefItem* BranchesModel::createBranchItem(bool notify, RefItem* parent, RM::Branc return link(notify, new RefBranch(parent, obj)); } -RefItem* BranchesModel::createTagItem(bool notify, RefItem* parent, RM::Tag* obj) +RefItem* BranchesModel::createTagItem(bool notify, RefItem* parent, const RM::Frontend::Tag& obj) { - if (!parent && obj->parentObject()->objType() != RM::CollectionNodeObject) { - parent = insertObject(notify, obj->parentObject()); + if (!parent /* && obj->parentObject()->objType() != RM::ObjTypes::CollectionNode */) { // ###REPOMAN + parent = insertObject(notify, obj.parent()); return NULL; } @@ -210,23 +209,25 @@ RefItem* BranchesModel::createTagItem(bool notify, RefItem* parent, RM::Tag* obj return link(notify, new RefTag(parent, obj)); } -RefItem* BranchesModel::createScopeItem(bool notify, RefItem* parent, RM::RefTreeNode* obj) +RefItem* BranchesModel::createScopeItem(bool notify, RefItem* parent, const RM::Frontend::RefTreeNode& obj) { if (!parent) { - RM::Base* parObj = obj->parentObject(); + RM::Frontend::Base parObj = obj.parent(); - if (parObj->objType() != RM::CollectionNodeObject) { + + #if 0 // ###REPOMAN + if (parObj->objType() != RM::ObjTypes::CollectionNode) { parent = insertObject(notify, parObj); - return NULL; + return nullptr; } - RM::CollectionNode* cn = static_cast(parObj); + RM::Frontend::CollectionNode* cn = static_cast(parObj); switch (cn->collectionType()) { - case RM::ctTags: + case RM::Frontend::ctTags: parent = mHeaderTags; break; - case RM::ctBranches: + case RM::Frontend::ctBranches: parent = mHeaderLocal; break; @@ -234,12 +235,13 @@ RefItem* BranchesModel::createScopeItem(bool notify, RefItem* parent, RM::RefTre // Should we assert here? return NULL; } + #endif } return link(notify, new RefScope(parent, obj)); } -RefItem* BranchesModel::createRemoteItem(bool notify, RefItem* parent, RM::Remote* obj) +RefItem* BranchesModel::createRemoteItem(bool notify, RefItem* parent, const RM::Frontend::Remote& obj) { if (!parent) { parent = mHeaderRemote; @@ -248,35 +250,36 @@ RefItem* BranchesModel::createRemoteItem(bool notify, RefItem* parent, RM::Remot return link(notify, new RefRemote(parent, obj)); } -RefItem* BranchesModel::insertObject(bool notify, RM::Base* obj) +RefItem* BranchesModel::insertObject(bool notify, const RM::Frontend::Base& obj) { if (!obj) { return NULL; } - qDebug() << obj->displayName(); + qDebug() << obj.displayName(); bool doChildren = false; - RefItem* parent = mObjToItems.value(obj->parentObject(), NULL); + RefItem* parent = mObjToItems.value(obj.parent(), NULL); RefItem* it = mObjToItems.value(obj, NULL); if (!it) { - switch (obj->objType()) { - case RM::BranchObject: - it = createBranchItem(notify, parent, static_cast(obj)); + + switch (obj.objType()) { + case RM::ObjTypes::Branch: + it = createBranchItem(notify, parent, obj.as()); break; - case RM::TagObject: - it = createTagItem(notify, parent, static_cast(obj)); + case RM::ObjTypes::Tag: + it = createTagItem(notify, parent, obj.as()); break; - case RM::RefTreeNodeObject: - it = createScopeItem(notify, parent, static_cast(obj)); + case RM::ObjTypes::RefTreeNode: + it = createScopeItem(notify, parent, obj.as()); doChildren = true; break; - case RM::RemoteObject: - it = createRemoteItem(notify, parent, static_cast(obj)); + case RM::ObjTypes::Remote: + it = createRemoteItem(notify, parent, obj.as()); doChildren = true; break; @@ -290,7 +293,7 @@ RefItem* BranchesModel::insertObject(bool notify, RM::Base* obj) mItemToObjs.insert(it, obj); if (doChildren) { - foreach(RM::Base* child, obj->childObjects()) { + foreach(RM::Frontend::Base child, obj.children()) { insertObject(notify, child); } } @@ -299,14 +302,14 @@ RefItem* BranchesModel::insertObject(bool notify, RM::Base* obj) return it; } -void BranchesModel::insertCollection(RM::CollectionNode* coll) +void BranchesModel::insertCollection(RM::Frontend::CollectionNode* coll) { - foreach(RM::Base* obj, coll->childObjects()) { + foreach(RM::Frontend::Base* obj, coll->childObjects()) { insertObject(false, obj); } } -void BranchesModel::updatedObject(RM::Base* obj) +void BranchesModel::updatedObject(RM::Frontend::Base* obj) { RefItem* it = mObjToItems.value(obj, NULL); if (!it) { @@ -334,7 +337,7 @@ void BranchesModel::deleteItem(RefItem* it) beginRemoveRows(itemToIndex(parent), pos, pos); - RM::Base* obj = it->object(); + RM::Frontend::Base* obj = it->object(); if (obj) { mObjToItems.remove(obj); mItemToObjs.remove(it); @@ -345,12 +348,12 @@ void BranchesModel::deleteItem(RefItem* it) endRemoveRows(); } -void BranchesModel::deletedObject(RM::Base* obj) +void BranchesModel::deletedObject(RM::Frontend::Base* obj) { deleteItem(mObjToItems.value(obj, NULL)); } -void BranchesModel::setRepository(RM::Repo* repo) +void BranchesModel::setRepository(RM::Frontend::Repo* repo) { if (mRepo == repo) { return; @@ -374,14 +377,14 @@ void BranchesModel::setRepository(RM::Repo* repo) insertCollection(mRepo->branches()); insertCollection(mRepo->tags()); - foreach (RM::Remote* rmRemote, repo->childObjects()) { + foreach (RM::Frontend::Remote* rmRemote, repo->childObjects()) { insertObject(false, rmRemote); } endResetModel(); } -void BranchesModel::onRefCreated(RM::Repo* repo, RM::Ref* ref) +void BranchesModel::onRefCreated(RM::Frontend::Repo* repo, RM::Frontend::Ref* ref) { if (repo != mRepo) { return; @@ -390,7 +393,7 @@ void BranchesModel::onRefCreated(RM::Repo* repo, RM::Ref* ref) insertObject(true, ref); } -void BranchesModel::onRefDestroyed(RM::Repo* repo, RM::Ref* ref) +void BranchesModel::onRefDestroyed(RM::Frontend::Repo* repo, RM::Frontend::Ref* ref) { if (repo != mRepo) { return; @@ -399,7 +402,7 @@ void BranchesModel::onRefDestroyed(RM::Repo* repo, RM::Ref* ref) deletedObject(ref); } -void BranchesModel::onRefTreeNodeAboutToBeDeleted(RM::Repo* repo, RM::RefTreeNode* obj) +void BranchesModel::onRefTreeNodeAboutToBeDeleted(RM::Frontend::Repo* repo, RM::Frontend::RefTreeNode* obj) { if (repo != mRepo) { return; @@ -408,7 +411,7 @@ void BranchesModel::onRefTreeNodeAboutToBeDeleted(RM::Repo* repo, RM::RefTreeNod deletedObject(obj); } -void BranchesModel::onRefMoved(RM::Repo* repo, RM::Ref* ref) +void BranchesModel::onRefMoved(RM::Frontend::Repo* repo, RM::Frontend::Ref* ref) { if (repo != mRepo) { return; diff --git a/Modules/RefsViews/Branches/BranchesModel.hpp b/Modules/RefsViews/Branches/BranchesModel.hpp index 87956ba8..895fef79 100644 --- a/Modules/RefsViews/Branches/BranchesModel.hpp +++ b/Modules/RefsViews/Branches/BranchesModel.hpp @@ -19,20 +19,16 @@ #ifndef MGV_BRANCHES_MODEL_HPP #define MGV_BRANCHES_MODEL_HPP -#include +#include "Branches/BranchesViewData.hpp" +#include "RefItem.hpp" + +#include "libMacGitverCore/RepoMan/Frontend/Branch.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Repo.hpp" #include "libGitWrap/Reference.hpp" #include "libGitWrap/Repository.hpp" -#include "Branches/BranchesViewData.hpp" -#include "RefItem.hpp" - -namespace RM -{ - class Ref; - class Repo; - class CollectionNode; -} +#include class RefItem; class RefScope; @@ -61,37 +57,37 @@ class BranchesModel : public QAbstractItemModel void gitError( const Git::Result& error ); private slots: - void onRefCreated(RM::Repo* repo, RM::Ref* ref); - void onRefDestroyed(RM::Repo* repo, RM::Ref* ref); - void onRefMoved(RM::Repo* repo, RM::Ref* ref); - void onRefTreeNodeAboutToBeDeleted(RM::Repo* repo, RM::RefTreeNode* obj); + void onRefCreated(const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref); + void onRefDestroyed(const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref); + void onRefMoved(const RM::Frontend::Repo& repo, const RM::Frontend::Reference& ref); + void onRefTreeNodeAboutToBeDeleted(const RM::Frontend::Repo& repo, const RM::Frontend::RefTreeNode& obj); private: QModelIndex itemToIndex(RefItem* item) const; - QModelIndex objectToIndex(RM::Base* obj) const; + QModelIndex objectToIndex(const RM::Frontend::Base& obj) const; RefItem* link(bool notify, RefItem* it); - void insertCollection(RM::CollectionNode* coll); - RefItem* insertObject(bool notify, RM::Base* obj); - RefItem* createBranchItem(bool notify, RefItem* parent, RM::Branch* obj); - RefItem* createTagItem(bool notify, RefItem* parent, RM::Tag* obj); - RefItem* createScopeItem(bool notify, RefItem* parent, RM::RefTreeNode* obj); - RefItem* createRemoteItem(bool notify, RefItem* parent, RM::Remote* obj); - - void updatedObject(RM::Base* obj); - void deletedObject(RM::Base* obj); + //void insertCollection(RM::CollectionNode* coll); + RefItem* insertObject(bool notify, const RM::Frontend::Base& obj); + RefItem* createBranchItem(bool notify, RefItem* parent, const RM::Frontend::Branch& obj); + RefItem* createTagItem(bool notify, RefItem* parent, const RM::Frontend::Tag& obj); + RefItem* createScopeItem(bool notify, RefItem* parent, const RM::Frontend::RefTreeNode& obj); + RefItem* createRemoteItem(bool notify, RefItem* parent, const RM::Frontend::Remote& obj); + + void updatedObject(const RM::Frontend::Base& obj); + void deletedObject(const RM::Frontend::Base& obj); void deleteItem(RefItem* it); private: - RM::Repo* mRepo; + RM::Frontend::Repo mRepo; RefRoot* mRoot; RefHeadline* mHeaderLocal; RefHeadline* mHeaderRemote; RefHeadline* mHeaderTags; - QHash mObjToItems; - QHash mItemToObjs; + QHash mObjToItems; + QHash mItemToObjs; }; #endif diff --git a/Modules/RefsViews/Branches/RefItem.cpp b/Modules/RefsViews/Branches/RefItem.cpp index dda9f28e..3c607cc3 100644 --- a/Modules/RefsViews/Branches/RefItem.cpp +++ b/Modules/RefsViews/Branches/RefItem.cpp @@ -47,9 +47,9 @@ RefItem::~RefItem() qDeleteAll( children ); } -RM::Base* RefItem::object() +RM::Frontend::Base RefItem::object() { - return NULL; + return nullptr; } int RefItem::itemPosition() @@ -140,7 +140,7 @@ QVariant RefBranch::data(int role) const switch (role) { case Qt::FontRole: - if (object()->isHead()) { + if (object().isHead()) { QFont f; f.setBold( true ); return f; @@ -175,7 +175,7 @@ QVariant RefTag::data(int role) const switch (role) { case Qt::EditRole: - return object()->name(); + return object().name(); } return RefItemObject::data(role); diff --git a/Modules/RefsViews/Branches/RefItem.hpp b/Modules/RefsViews/Branches/RefItem.hpp index 8ce32359..0ebb5bdb 100644 --- a/Modules/RefsViews/Branches/RefItem.hpp +++ b/Modules/RefsViews/Branches/RefItem.hpp @@ -22,25 +22,16 @@ #include "libHeavenIcons/Icon.hpp" -#include "libMacGitverCore/RepoMan/RefTreeNode.hpp" -#include "libMacGitverCore/RepoMan/Ref.hpp" -#include "libMacGitverCore/RepoMan/Branch.hpp" -#include "libMacGitverCore/RepoMan/Tag.hpp" -#include "libMacGitverCore/RepoMan/Remote.hpp" +#include "libMacGitverCore/RepoMan/Frontend/RefTreeNode.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Reference.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Branch.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Tag.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Remote.hpp" #include #include #include -namespace RM -{ - class Base; - class Ref; - class Branch; - class RefTreeNode; - class Namespace; -} - class BranchesModel; class RefItem @@ -74,7 +65,7 @@ class RefItem public: int itemPosition(); virtual ItemType type() const = 0; - virtual RM::Base* object(); + virtual RM::Frontend::Base object(); public: RefItem* parent; @@ -118,28 +109,30 @@ template class RefItemObject : public RefItem { protected: - RefItemObject(RefItem* parent, T* object) + RefItemObject(RefItem* parent, const T& object) : RefItem(parent) , mObject(object) {} public: - const T* object() const { + const T& object() const { return mObject; } - T* object() { + #if 0 // ###REPOMAN got unsafe now, right? + T& object() { return mObject; } + #endif QVariant data(int role) const { if (mObject) { switch (role) { case Qt::DisplayRole: - return mObject->displayName(); + return mObject.displayName(); case Qt::DecorationRole: - Heaven::IconRef iref = mObject->icon(true); + Heaven::IconRef iref = mObject.icon(true); Heaven::Icon icon = iref.icon(); return icon.pixmap(); } @@ -148,16 +141,16 @@ class RefItemObject : public RefItem } protected: - T* mObject; + T mObject; }; -class RefScope : public RefItemObject +class RefScope : public RefItemObject { public: enum { StaticType = Scope }; public: - RefScope(RefItem* parent, RM::RefTreeNode* obj) + RefScope(RefItem* parent, const RM::Frontend::RefTreeNode& obj) : RefItemObject(parent, obj) {} @@ -176,13 +169,13 @@ class RefNameSpace : public RefScope ItemType type() const; }; -class RefRemote : public RefItemObject +class RefRemote : public RefItemObject { public: enum { StaticType = Remote }; public: - RefRemote(RefItem* parent, RM::Remote* remote) + RefRemote(RefItem* parent, const RM::Frontend::Remote& remote) : RefItemObject(parent, remote) { } @@ -191,13 +184,13 @@ class RefRemote : public RefItemObject ItemType type() const; }; -class RefBranch : public RefItemObject +class RefBranch : public RefItemObject { public: enum { StaticType = Branch }; public: - RefBranch(RefItem* parent, RM::Branch* branch) + RefBranch(RefItem* parent, const RM::Frontend::Branch& branch) : RefItemObject(parent, branch) { } @@ -208,13 +201,13 @@ class RefBranch : public RefItemObject }; -class RefTag : public RefItemObject +class RefTag : public RefItemObject { public: enum { StaticType = Tag }; public: - RefTag(RefItem* parent, RM::Tag* tag) + RefTag(RefItem* parent, const RM::Frontend::Tag& tag) : RefItemObject(parent, tag) { } diff --git a/Modules/RefsViews/RefRenameDialog.cpp b/Modules/RefsViews/RefRenameDialog.cpp index cd111d29..0b5f7688 100644 --- a/Modules/RefsViews/RefRenameDialog.cpp +++ b/Modules/RefsViews/RefRenameDialog.cpp @@ -24,10 +24,10 @@ #include "libGitWrap/RefName.hpp" -#include "libMacGitverCore/RepoMan/Branch.hpp" -#include "libMacGitverCore/RepoMan/Repo.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Branch.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Repo.hpp" -RefRenameDialog::RefRenameDialog(const Git::Reference &ref, RM::Repo* repo) +RefRenameDialog::RefRenameDialog(const Git::Reference &ref, const RM::Frontend::Repo& repo) : BlueSky::Dialog() , mRef(ref) , mRepo(repo) @@ -64,7 +64,9 @@ void RefRenameDialog::accept() mRef.rename(mGitResult, newRefName); if (mGitResult) { - mRepo->refresh(); + // ###REPOMAN When making this a service, we need to refresh (but all services need to + // do that). + //mRepo->refresh(); QDialog::accept(); return; } diff --git a/Modules/RefsViews/RefRenameDialog.hpp b/Modules/RefsViews/RefRenameDialog.hpp index 79e554e5..08d08136 100644 --- a/Modules/RefsViews/RefRenameDialog.hpp +++ b/Modules/RefsViews/RefRenameDialog.hpp @@ -23,7 +23,7 @@ #include "libGitWrap/Result.hpp" #include "libGitWrap/Reference.hpp" -#include "libMacGitverCore/RepoMan/Repo.hpp" +#include "libMacGitverCore/RepoMan/Frontend/Repo.hpp" #include "ui_RefRenameDialog.h" @@ -33,7 +33,7 @@ class RefRenameDialog { Q_OBJECT public: - RefRenameDialog(const Git::Reference& ref, RM::Repo* repo); + RefRenameDialog(const Git::Reference& ref, const RM::Frontend::Repo& repo); const Git::Result &gitResult() const; @@ -41,7 +41,7 @@ private slots: void accept(); private: - Git::Result mGitResult; - Git::Reference mRef; - RM::Repo* mRepo; + Git::Result mGitResult; + Git::Reference mRef; + RM::Frontend::Repo mRepo; }; diff --git a/Modules/RepoManLogger/Listener.cpp b/Modules/RepoManLogger/Listener.cpp index 5c223b55..ae3c0bf5 100644 --- a/Modules/RepoManLogger/Listener.cpp +++ b/Modules/RepoManLogger/Listener.cpp @@ -17,10 +17,10 @@ * */ -#include "libMacGitverCore/RepoMan/Repo.hpp" -#include "libMacGitverCore/RepoMan/Tag.hpp" -#include "libMacGitverCore/RepoMan/Branch.hpp" -#include "libMacGitverCore/RepoMan/Submodule.hpp" +#include "libRepoMan/RepoMan.hpp" +#include "libRepoMan/Frontend/Tag.hpp" +#include "libRepoMan/Frontend/Branch.hpp" +#include "libRepoMan/Frontend/Submodule.hpp" #include "Listener.hpp" #include "TemplateNames.hpp" @@ -28,188 +28,188 @@ Listener::Listener(Log::Channel channel) : repoManChannel(channel) { - RM::Events::addReceiver(this); + RM::CompatEvents::addReceiver(this); } Listener::~Listener() { - RM::Events::delReceiver(this); + RM::CompatEvents::delReceiver(this); } -void Listener::repositoryOpened(RM::Repo* repo) +void Listener::repositoryOpened(const RM::Frontend::Repo& repo) { Log::Event e = Log::Event::create(TMPL_REPO_ACTIVITY); Q_ASSERT(e); e.setParam(QStringLiteral("Action"), tr("opened")); - e.setParam(QStringLiteral("RepoName"), repo->displayAlias()); + e.setParam(QStringLiteral("RepoName"), repo.displayAlias()); repoManChannel.addEvent(e); } -void Listener::repositoryAboutToClose(RM::Repo* repo) +void Listener::repositoryAboutToClose(const RM::Frontend::Repo& repo) { Log::Event e = Log::Event::create(TMPL_REPO_ACTIVITY); Q_ASSERT(e); e.setParam(QStringLiteral("Action"), tr("closed")); - e.setParam(QStringLiteral("RepoName"), repo->displayAlias()); + e.setParam(QStringLiteral("RepoName"), repo.displayAlias()); repoManChannel.addEvent(e); } -void Listener::repositoryActivated(RM::Repo* repo) +void Listener::repositoryActivated(const RM::Frontend::Repo& repo) { Log::Event e = Log::Event::create(TMPL_REPO_ACTIVITY); Q_ASSERT(e); e.setParam(QStringLiteral("Action"), tr("activated")); - e.setParam(QStringLiteral("RepoName"), repo->displayAlias()); + e.setParam(QStringLiteral("RepoName"), repo.displayAlias()); repoManChannel.addEvent(e); } -void Listener::repositoryDeactivated(RM::Repo* repo) +void Listener::repositoryDeactivated(const RM::Frontend::Repo& repo) { // We don't want to report deactivation } -void Listener::objectCreated(RM::Repo* repo, RM::Base* object) +void Listener::objectCreated(const RM::Frontend::Base& object) { } -void Listener::objectAboutToBeDeleted(RM::Repo* repo, RM::Base* object) +void Listener::objectAboutToBeDeleted(const RM::Frontend::Base& object) { } -void Listener::refTreeNodeCreated(RM::Repo* repo, RM::RefTreeNode* node) +void Listener::refTreeNodeCreated(const RM::Frontend::RefTreeNode& node) { } -void Listener::refTreeNodeAboutToBeDeleted(RM::Repo* repo, RM::RefTreeNode* node) +void Listener::refTreeNodeAboutToBeDeleted(const RM::Frontend::RefTreeNode& node) { } -void Listener::refCreated(RM::Repo* repo, RM::Ref* ref) +void Listener::refCreated(const RM::Frontend::Reference& ref) { } -void Listener::refAboutToBeDeleted(RM::Repo* repo, RM::Ref* ref) +void Listener::refAboutToBeDeleted(const RM::Frontend::Reference& ref) { } -void Listener::refMoved(RM::Repo* repo, RM::Ref* ref) +void Listener::refMoved(const RM::Frontend::Reference& ref) { } -void Listener::refHeadDetached(RM::Repo* repo, RM::Ref* ref) +void Listener::refHeadDetached(const RM::Frontend::Reference& ref) { } -void Listener::tagCreated(RM::Repo* repo, RM::Tag* tag) +void Listener::tagCreated(const RM::Frontend::Tag& tag) { Log::Event e = Log::Event::create(TMPL_FOUND_NEW_REF); Q_ASSERT(e); e.setParam(QStringLiteral("Type"), tr("tag")); - e.setParam(QStringLiteral("ObjName"), tag->displayName()); - e.setParam(QStringLiteral("SHA"), tag->displaySha1()); - e.setParam(QStringLiteral("RepoName"), repo->displayAlias()); + e.setParam(QStringLiteral("ObjName"), tag.displayName()); + e.setParam(QStringLiteral("SHA"), tag.displaySha1()); + e.setParam(QStringLiteral("RepoName"), tag.repository().displayAlias()); repoManChannel.addEvent(e); } -void Listener::tagAboutToBeDeleted(RM::Repo* repo, RM::Tag* tag) +void Listener::tagAboutToBeDeleted(const RM::Frontend::Tag& tag) { } -void Listener::branchCreated(RM::Repo* repo, RM::Branch* branch) +void Listener::branchCreated(const RM::Frontend::Branch& branch) { } -void Listener::branchAboutToBeDeleted(RM::Repo* repo, RM::Branch* branch) +void Listener::branchAboutToBeDeleted(const RM::Frontend::Branch& branch) { } -void Listener::branchMoved(RM::Repo* repo, RM::Branch* branch) +void Listener::branchMoved(const RM::Frontend::Branch& branch) { Log::Event e = Log::Event::create(TMPL_BRANCH_MOVED); Q_ASSERT(e); - e.setParam(QStringLiteral("ObjName"), branch->displayName()); - e.setParam(QStringLiteral("SHA"), branch->displaySha1()); - e.setParam(QStringLiteral("RepoName"), repo->displayAlias()); + e.setParam(QStringLiteral("ObjName"), branch.displayName()); + e.setParam(QStringLiteral("SHA"), branch.displaySha1()); + e.setParam(QStringLiteral("RepoName"), branch.repository().displayAlias()); repoManChannel.addEvent(e); } -void Listener::branchUpstreamChanged(RM::Repo* repo, RM::Branch* branch) +void Listener::branchUpstreamChanged(const RM::Frontend::Branch& branch) { } -void Listener::namespaceCreated(RM::Repo* repo, RM::Namespace* nameSpace) +void Listener::namespaceCreated(const RM::Frontend::Namespace& nameSpace) { } -void Listener::namespaceAboutToBeDeleted(RM::Repo* repo, RM::Namespace* nameSpace) +void Listener::namespaceAboutToBeDeleted(const RM::Frontend::Namespace& nameSpace) { } -void Listener::refLogChanged(RM::Repo* repo, RM::RefLog* reflog) +void Listener::refLogChanged(const RM::Frontend::RefLog& reflog) { } -void Listener::refLogNewEntry(RM::Repo* repo, RM::RefLog* reflog) +void Listener::refLogNewEntry(const RM::Frontend::RefLog& reflog) { } -void Listener::stageCreated(RM::Repo* repo, RM::Ref* ref) +void Listener::stageCreated(const RM::Frontend::Reference& ref) { } -void Listener::stageAboutToBeDeleted(RM::Repo* repo, RM::Ref* ref) +void Listener::stageAboutToBeDeleted(const RM::Frontend::Reference& ref) { } -void Listener::remoteCreated(RM::Repo* repo, RM::Remote* remote) +void Listener::remoteCreated(const RM::Frontend::Remote& remote) { } -void Listener::remoteAboutToBeDeleted(RM::Repo* repo, RM::Remote* remote) +void Listener::remoteAboutToBeDeleted(const RM::Frontend::Remote& remote) { } -void Listener::remoteModified(RM::Repo* repo, RM::Remote* remote) +void Listener::remoteModified(const RM::Frontend::Remote& remote) { } -void Listener::submoduleCreated(RM::Repo* repo, RM::Submodule* submodule) +void Listener::submoduleCreated(const RM::Frontend::Submodule& submodule) { Log::Event e = Log::Event::create(TMPL_FOUND_NEW_SM); Q_ASSERT(e); - e.setParam(QStringLiteral("ObjName"), submodule->displayName()); - e.setParam(QStringLiteral("RepoName"), repo->displayAlias()); + e.setParam(QStringLiteral("ObjName"), submodule.displayName()); + e.setParam(QStringLiteral("RepoName"), submodule.repository().displayAlias()); repoManChannel.addEvent(e); } -void Listener::submoduleAboutToBeDeleted(RM::Repo* repo, RM::Submodule* submodule) +void Listener::submoduleAboutToBeDeleted(const RM::Frontend::Submodule& submodule) { } -void Listener::submoduleMoved(RM::Repo* repo, RM::Submodule* submodule) +void Listener::submoduleMoved(const RM::Frontend::Submodule& submodule) { } -void Listener::repositoryStateChanged(RM::Repo* repo) +void Listener::repositoryStateChanged(const RM::Frontend::Repo& repo) { } -void Listener::indexUpdated(RM::Repo* repo) +void Listener::indexUpdated() { } -void Listener::workTreeUpdated(RM::Repo* repo) +void Listener::workTreeUpdated() { } diff --git a/Modules/RepoManLogger/Listener.hpp b/Modules/RepoManLogger/Listener.hpp index 2652dac4..8fd867e3 100644 --- a/Modules/RepoManLogger/Listener.hpp +++ b/Modules/RepoManLogger/Listener.hpp @@ -19,14 +19,14 @@ #pragma once -#include - -#include "libMacGitverCore/RepoMan/Events.hpp" +#include "libRepoMan/Events/Compat.hpp" #include "libLogger/Channel.hpp" #include "libLogger/Event.hpp" -class Listener : public RM::EventsInterface +#include + +class Listener : public RM::CompatEventsInterface { Q_DECLARE_TR_FUNCTIONS(RepoManLogger) @@ -35,39 +35,39 @@ class Listener : public RM::EventsInterface ~Listener(); public: - void repositoryOpened(RM::Repo* repo); - void repositoryAboutToClose(RM::Repo* repo); - void repositoryActivated(RM::Repo* repo); - void repositoryDeactivated(RM::Repo* repo); - void objectCreated(RM::Repo* repo, RM::Base* object); - void objectAboutToBeDeleted(RM::Repo* repo, RM::Base* object); - void refTreeNodeCreated(RM::Repo* repo, RM::RefTreeNode* node); - void refTreeNodeAboutToBeDeleted(RM::Repo* repo, RM::RefTreeNode* node); - void refCreated(RM::Repo* repo, RM::Ref* ref); - void refAboutToBeDeleted(RM::Repo* repo, RM::Ref* ref); - void refMoved(RM::Repo* repo, RM::Ref* ref); - void refHeadDetached(RM::Repo* repo, RM::Ref* ref); - void tagCreated(RM::Repo* repo, RM::Tag* tag); - void tagAboutToBeDeleted(RM::Repo* repo, RM::Tag* tag); - void branchCreated(RM::Repo* repo, RM::Branch* branch); - void branchAboutToBeDeleted(RM::Repo* repo, RM::Branch* branch); - void branchMoved(RM::Repo* repo, RM::Branch* branch); - void branchUpstreamChanged(RM::Repo* repo, RM::Branch* branch); - void namespaceCreated(RM::Repo* repo, RM::Namespace* nameSpace); - void namespaceAboutToBeDeleted(RM::Repo* repo, RM::Namespace* nameSpace); - void refLogChanged(RM::Repo* repo, RM::RefLog* reflog); - void refLogNewEntry(RM::Repo* repo, RM::RefLog* reflog); - void stageCreated(RM::Repo* repo, RM::Ref* ref); - void stageAboutToBeDeleted(RM::Repo* repo, RM::Ref* ref); - void remoteCreated(RM::Repo* repo, RM::Remote* remote); - void remoteAboutToBeDeleted(RM::Repo* repo, RM::Remote* remote); - void remoteModified(RM::Repo* repo, RM::Remote* remote); - void submoduleCreated(RM::Repo* repo, RM::Submodule* submodule); - void submoduleAboutToBeDeleted(RM::Repo* repo, RM::Submodule* submodule); - void submoduleMoved(RM::Repo* repo, RM::Submodule* submodule); - void repositoryStateChanged(RM::Repo* repo); - void indexUpdated(RM::Repo* repo); - void workTreeUpdated(RM::Repo* repo); + void repositoryOpened(const RM::Frontend::Repo& repo); + void repositoryAboutToClose(const RM::Frontend::Repo& repo); + void repositoryActivated(const RM::Frontend::Repo& repo); + void repositoryDeactivated(const RM::Frontend::Repo& repo); + void objectCreated(const RM::Frontend::Base& object); + void objectAboutToBeDeleted(const RM::Frontend::Base& object); + void refTreeNodeCreated(const RM::Frontend::RefTreeNode& node); + void refTreeNodeAboutToBeDeleted(const RM::Frontend::RefTreeNode& node); + void refCreated(const RM::Frontend::Reference& ref); + void refAboutToBeDeleted(const RM::Frontend::Reference& ref); + void refMoved(const RM::Frontend::Reference& ref); + void refHeadDetached(const RM::Frontend::Reference& ref); + void tagCreated(const RM::Frontend::Tag& tag); + void tagAboutToBeDeleted(const RM::Frontend::Tag& tag); + void branchCreated(const RM::Frontend::Branch& branch); + void branchAboutToBeDeleted(const RM::Frontend::Branch& branch); + void branchMoved(const RM::Frontend::Branch& branch); + void branchUpstreamChanged(const RM::Frontend::Branch& branch); + void namespaceCreated(const RM::Frontend::Namespace& nameSpace); + void namespaceAboutToBeDeleted(const RM::Frontend::Namespace& nameSpace); + void refLogChanged(const RM::Frontend::RefLog& reflog); + void refLogNewEntry(const RM::Frontend::RefLog& reflog); + void stageCreated(const RM::Frontend::Reference& ref); + void stageAboutToBeDeleted(const RM::Frontend::Reference& ref); + void remoteCreated(const RM::Frontend::Remote& remote); + void remoteAboutToBeDeleted(const RM::Frontend::Remote& remote); + void remoteModified(const RM::Frontend::Remote& remote); + void submoduleCreated(const RM::Frontend::Submodule& submodule); + void submoduleAboutToBeDeleted(const RM::Frontend::Submodule& submodule); + void submoduleMoved(const RM::Frontend::Submodule& submodule); + void repositoryStateChanged(const RM::Frontend::Repo& repo); + void indexUpdated(); + void workTreeUpdated(); private: Log::Channel repoManChannel; diff --git a/Modules/RepoManLogger/RepoManLoggerModule.cpp b/Modules/RepoManLogger/RepoManLoggerModule.cpp index 7b8ec21b..6c51d615 100644 --- a/Modules/RepoManLogger/RepoManLoggerModule.cpp +++ b/Modules/RepoManLogger/RepoManLoggerModule.cpp @@ -25,7 +25,7 @@ #include "TemplateNames.hpp" RepoManLoggerModule::RepoManLoggerModule() - : listener(NULL) + : listener(nullptr) { } @@ -49,7 +49,7 @@ void RepoManLoggerModule::deinitialize() // Channel should also be kept registered // But listener has to be destroyed... delete listener; - listener = NULL; + listener = nullptr; } void RepoManLoggerModule::setupTemplates() diff --git a/Modules/Repository/CreateRepositoryDlg.cpp b/Modules/Repository/CreateRepositoryDlg.cpp index a60ba1db..c62330d2 100644 --- a/Modules/Repository/CreateRepositoryDlg.cpp +++ b/Modules/Repository/CreateRepositoryDlg.cpp @@ -20,8 +20,7 @@ #include "libMacGitverCore/Config/Config.h" #include "libMacGitverCore/App/MacGitver.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" - +#include "libRepoMan/RepoMan.hpp" #include "CreateRepositoryDlg.h" CreateRepositoryDlg::CreateRepositoryDlg() diff --git a/Modules/Repository/RepoInfoModel.cpp b/Modules/Repository/RepoInfoModel.cpp index c9886c7e..968c9b85 100644 --- a/Modules/Repository/RepoInfoModel.cpp +++ b/Modules/Repository/RepoInfoModel.cpp @@ -14,61 +14,80 @@ * */ +#include "RepoInfoModel.hpp" + #include "libMacGitverCore/App/MacGitver.hpp" #include "libMacGitverCore/Config/Config.h" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" - +#include "libRepoMan/RepoMan.hpp" #include "libHeavenIcons/IconRef.hpp" #include "libHeavenIcons/Icon.hpp" -#include "RepoInfoModel.hpp" +struct RepoInfoModel::RepoInfo +{ + RepoInfo(RM::Frontend::Repo&& r) + : mRepo(std::move(r)) + {} + + ~RepoInfo() + { + qDeleteAll(mChildren); + } + + RM::Frontend::Repo mRepo; + RepoInfoModel::RepoInfos mChildren; +}; RepoInfoModel::RepoInfoModel() { - mRepoMan = &MacGitver::repoMan(); + RM::RepoMan& rm = RM::RepoMan::instance(); - connect( mRepoMan, &RM::RepoMan::repositoryDeactivated, - this, &RepoInfoModel::invalidateRepository); + connect( &rm, &RM::RepoMan::repositoryDeactivated, + this, &RepoInfoModel::invalidateRepository); - connect( mRepoMan, &RM::RepoMan::repositoryActivated, - this, &RepoInfoModel::invalidateRepository); + connect( &rm, &RM::RepoMan::repositoryActivated, + this, &RepoInfoModel::invalidateRepository); - connect( mRepoMan, &RM::RepoMan::repositoryOpened, - this, &RepoInfoModel::invalidateRepository); + connect( &rm, &RM::RepoMan::repositoryOpened, + this, &RepoInfoModel::invalidateRepository); +} + +RepoInfoModel::~RepoInfoModel() +{ + qDeleteAll(mRoots); } int RepoInfoModel::rowCount( const QModelIndex& parent ) const { - if( parent.isValid() ) - { - RM::Repo* info = index2Info( parent ); - return info ? info->submodules().count() : 0; + if (parent.isValid()) { + RM::Frontend::Repo info = index2Repo( parent ); + return info ? info.submodules().count() : 0; } - else - { - return mRepoMan->repositories().count(); + else { + return RM::RepoMan::instance().repositories().count(); } } -int RepoInfoModel::columnCount( const QModelIndex& parent ) const +int RepoInfoModel::columnCount(const QModelIndex& parent) const { return 1; } -QVariant RepoInfoModel::data( const QModelIndex& index, int role ) const +QVariant RepoInfoModel::data(const QModelIndex& index, int role) const { - if( !index.isValid() ) return QVariant(); + if (!index.isValid()) { + return QVariant(); + } - RM::Repo* info = index2Info( index ); - if( info ) - { - switch(role) { + RM::Frontend::Repo info = index2Repo(index); + if (info) { + + switch (role) { case Qt::DisplayRole: - return info->displayAlias(); + return info.displayAlias(); case Qt::DecorationRole: { - Heaven::IconRef icon = info->icon().clone(); + Heaven::IconRef icon = info.icon().clone(); QFont f; int size = (f.pixelSize() <= 0) ? f.pointSize() : f.pixelSize(); icon.setSize( qMax(size + 2, 16) ); @@ -79,11 +98,11 @@ QVariant RepoInfoModel::data( const QModelIndex& index, int role ) const { QFont f1, f2; f2.setBold( true ); - return info->isActive() ? f2 : f1; + return info.isActive() ? f2 : f1; } case IsActive: - return info->isActive(); + return info.isActive(); case Qt::ToolTipRole: return trUtf8( @@ -100,81 +119,74 @@ QVariant RepoInfoModel::data( const QModelIndex& index, int role ) const "
Branch: %2
" "" "") - .arg(info->displayName()) - .arg(info->branchDisplay()); + .arg(info.displayName()) + .arg(info.branchDisplay()); } } return QVariant(); } -QModelIndex RepoInfoModel::index( int row, int column, const QModelIndex& parent ) const +QModelIndex RepoInfoModel::index(int row, int column, const QModelIndex& parent) const { Q_UNUSED(column); - RM::Repo::List list; + RM::Frontend::Repo::List list; - if( parent.isValid() ) - { - RM::Repo* infoParent = index2Info( parent ); - if( !infoParent ) - { + if (parent.isValid()) { + + RM::Frontend::Repo repoParent = index2Repo(parent); + + if (!repoParent) { return QModelIndex(); } - foreach (RM::Repo* r, infoParent->submodules()) { - list.append(r); - } + list = repoParent.submodules(); } - else - { - list = mRepoMan->repositories(); + else { + list = RM::RepoMan::instance().repositories(); } - if( row >= list.count() || row < 0 ) - { + if (row >= list.count() || row < 0) { return QModelIndex(); } - return info2Index( list.at( row ) ); + return repo2Index(list.at(row)); } -QModelIndex RepoInfoModel::parent( const QModelIndex& child ) const +QModelIndex RepoInfoModel::parent(const QModelIndex& child) const { - if( !child.isValid() ) - { + if (!child.isValid()) { return QModelIndex(); } - RM::Repo* info = index2Info( child ); - if( !info || !info->parentRepository() ) - { + RM::Frontend::Repo info = index2Repo(child); + + if (!info || !info.parentRepository()) { return QModelIndex(); } - return info2Index( info->parentRepository() ); + return repo2Index(info.parentRepository()); } -RM::Repo* RepoInfoModel::index2Info( const QModelIndex& index ) const +RM::Frontend::Repo RepoInfoModel::index2Repo(const QModelIndex& index) const { - return static_cast< RM::Repo* >( index.internalPointer() ); + RepoInfo* ri = index2info(index); + return ri ? ri->mRepo : RM::Frontend::Repo(); } -QModelIndex RepoInfoModel::info2Index(RM::Repo* info) const +QModelIndex RepoInfoModel::repo2Index(const RM::Frontend::Repo& repo) const { int row = 0; - if( !info ) - { + if (!repo) { return QModelIndex(); } - if( info->parentRepository() ) +#if 0 + if (info->parentRepository()) { - RM::Repo::Set sms = info->parentRepository()->submodules(); - RM::Repo::List list; - foreach (RM::Repo* r, sms) { - list.append(r); - } + RM::Repo::List list = info->parentRepository()->submodules(); + // ###REPOMAN Shouldn't this be sorted? row = list.indexOf(info); } else @@ -188,18 +200,27 @@ QModelIndex RepoInfoModel::info2Index(RM::Repo* info) const } return createIndex( row, 0, info ); +#endif } -void RepoInfoModel::invalidateRepository(RM::Repo *info) +void RepoInfoModel::invalidateRepository(const RM::Frontend::Repo& info) { - if ( !info ) return; + if (!info) { + return; + } + + QModelIndex index = repo2Index(info); + emit dataChanged(index, index); +} - QModelIndex index = info2Index( info ); - emit dataChanged( index, index ); +RepoInfoModel::RepoInfo* RepoInfoModel::index2info(const QModelIndex& index) const +{ + return nullptr; } -void RepoInfoModel::repositoryOpened(RM::Repo *info) +void RepoInfoModel::repositoryOpened(const RM::Frontend::Repo& info) { +#if 0 if (!info || info->parentRepository()) { return; } @@ -218,11 +239,13 @@ void RepoInfoModel::repositoryOpened(RM::Repo *info) int row = mRepoMan->repositories().count() - 1; emit beginInsertRows(QModelIndex(), row, row); emit endInsertRows(); +#endif } -void RepoInfoModel::repositoryChildAdded(RM::Repo* parent, RM::Repo* child) +void RepoInfoModel::repositoryChildAdded(const RM::Frontend::Repo& parent, const RM::Frontend::Repo& child) { - QModelIndex parentIndex = info2Index(parent); +#if 0 + QModelIndex parentIndex = repo2Index(parent); // we add a row just at the end of the root. This is stupid. But that's the way it works when // a model actually isn't a model... @@ -230,4 +253,5 @@ void RepoInfoModel::repositoryChildAdded(RM::Repo* parent, RM::Repo* child) int row = parent->submodules().count() - 1; emit beginInsertRows(parentIndex, row, row); emit endInsertRows(); +#endif } diff --git a/Modules/Repository/RepoInfoModel.hpp b/Modules/Repository/RepoInfoModel.hpp index 31e261f8..599d54cb 100644 --- a/Modules/Repository/RepoInfoModel.hpp +++ b/Modules/Repository/RepoInfoModel.hpp @@ -14,22 +14,18 @@ * */ -#ifndef MGV_REPO_INFO_MODEL_HPP -#define MGV_REPO_INFO_MODEL_HPP +#pragma once #include -namespace RM -{ - class Repo; - class RepoMan; -} +#include "libRepoMan/RepoMan.hpp" class RepoInfoModel : public QAbstractItemModel { Q_OBJECT public: RepoInfoModel(); + ~RepoInfoModel(); enum ExtraRoles { @@ -37,23 +33,28 @@ class RepoInfoModel : public QAbstractItemModel }; public: - int rowCount( const QModelIndex& parent = QModelIndex() ) const; - int columnCount( const QModelIndex& parent = QModelIndex() ) const; - QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const; - QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const; - QModelIndex parent( const QModelIndex& child ) const; + int rowCount(const QModelIndex& parent = QModelIndex()) const; + int columnCount(const QModelIndex& parent = QModelIndex()) const; + QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex& child) const; public: - RM::Repo* index2Info( const QModelIndex& index ) const; - QModelIndex info2Index( RM::Repo* info ) const; + RM::Frontend::Repo index2Repo(const QModelIndex& index) const; + QModelIndex repo2Index(const RM::Frontend::Repo& repo) const; -public slots: - void invalidateRepository(RM::Repo* info); - void repositoryOpened(RM::Repo* info); - void repositoryChildAdded(RM::Repo* parent, RM::Repo* child); +private: + struct RepoInfo; + using RepoInfos = QVector; private: - RM::RepoMan* mRepoMan; -}; + RepoInfo* index2info(const QModelIndex& index) const; -#endif +private slots: + void invalidateRepository(const RM::Frontend::Repo& repo); + void repositoryOpened(const RM::Frontend::Repo& repo); + void repositoryChildAdded(const RM::Frontend::Repo& parent, const RM::Frontend::Repo& child); + +private: + RepoInfos mRoots; +}; diff --git a/Modules/Repository/RepoTreeView.cpp b/Modules/Repository/RepoTreeView.cpp index 55b44df5..3b7e7189 100644 --- a/Modules/Repository/RepoTreeView.cpp +++ b/Modules/Repository/RepoTreeView.cpp @@ -20,8 +20,7 @@ #include "libMacGitverCore/Widgets/TreeViewCtxMenu.hpp" #include "libMacGitverCore/App/MacGitver.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" -#include "libMacGitverCore/RepoMan/Repo.hpp" +#include "libRepoMan/RepoMan.hpp" #include "RepoTreeView.hpp" #include "RepoInfoModel.hpp" @@ -79,7 +78,8 @@ QModelIndex RepoTreeView::deeplyMapToSource( QModelIndex current ) const void RepoTreeView::contextMenu( const QModelIndex& index, const QPoint& globalPos ) { - RM::Repo* info = mModel->index2Info(deeplyMapToSource(index)); +#if 0 + RM::Repo* info = mModel->index2Repo(deeplyMapToSource(index)); if (info) { Heaven::Menu* menu = info->isSubModule() ? menuCtxMenuSMRepo : menuCtxMenuRepo; @@ -88,23 +88,26 @@ void RepoTreeView::contextMenu( const QModelIndex& index, const QPoint& globalPo menu->showPopup( globalPos ); } +#endif } void RepoTreeView::onCtxActivate() { +#if 0 Heaven::Action* action = qobject_cast< Heaven::Action* >( sender() ); - if( action ) - { + if (action) { RM::Repo* info = qobject_cast< RM::Repo* >( action->activatedBy() ); if( info ) { MacGitver::repoMan().activate( info ); } } +#endif } void RepoTreeView::onCtxClose() { +#if 0 Heaven::Action* action = qobject_cast< Heaven::Action* >( sender() ); if( action ) { @@ -114,10 +117,12 @@ void RepoTreeView::onCtxClose() info->close(); } } +#endif } -void RepoTreeView::onRepoActivated(RM::Repo* repo) +void RepoTreeView::onRepoActivated(const RM::Frontend::Repo& repo) { +#if 0 BlueSky::ContextKeys keys = mkKeys(); keys.set("RepoName", repo->path()); @@ -132,15 +137,18 @@ void RepoTreeView::onRepoActivated(RM::Repo* repo) } setCurrentContext(ctx); +#endif } -void RepoTreeView::onRepoDeactivated(RM::Repo* repo) +void RepoTreeView::onRepoDeactivated(const RM::Frontend::Repo& repo) { +#if 0 RepositoryContext* ctx = qobject_cast< RepositoryContext* >(currentContext()); if (ctx && ctx->repository() == repo) { setCurrentContext( NULL ); } +#endif } BlueSky::ViewContext* RepoTreeView::createContextObject() const diff --git a/Modules/Repository/RepoTreeView.hpp b/Modules/Repository/RepoTreeView.hpp index 5904fdbd..94259191 100644 --- a/Modules/Repository/RepoTreeView.hpp +++ b/Modules/Repository/RepoTreeView.hpp @@ -14,8 +14,7 @@ * */ -#ifndef MGV_REPO_TREE_VIEW_HPP -#define MGV_REPO_TREE_VIEW_HPP +#pragma once #include "libBlueSky/Contexts.hpp" @@ -23,14 +22,11 @@ class QModelIndex; -namespace RM -{ - class Repo; -} - class RepoInfoModel; class TreeViewCtxMenu; +#include "libRepoMan/RepoMan.hpp" + class RepoTreeView : public BlueSky::ContextView , private RepoTreeViewCtxMenu @@ -50,8 +46,8 @@ private slots: // from mRepos void contextMenu( const QModelIndex& index, const QPoint& globalPos ); private slots: // for MacGitver::repoMan() - void onRepoActivated(RM::Repo* repo); - void onRepoDeactivated(RM::Repo* repo); + void onRepoActivated(const RM::Frontend::Repo& repo); + void onRepoDeactivated(const RM::Frontend::Repo& repo); private: QModelIndex deeplyMapToSource( QModelIndex current ) const; @@ -61,5 +57,3 @@ private slots: // for MacGitver::repoMan() RepoInfoModel* mModel; TreeViewCtxMenu* mRepos; }; - -#endif diff --git a/Modules/Repository/RepositoryModule.cpp b/Modules/Repository/RepositoryModule.cpp index 38a9558f..7197406f 100644 --- a/Modules/Repository/RepositoryModule.cpp +++ b/Modules/Repository/RepositoryModule.cpp @@ -24,8 +24,7 @@ #include "libMacGitverCore/Config/Config.h" #include "libMacGitverCore/App/MacGitver.hpp" -#include "libMacGitverCore/RepoMan/RepoMan.hpp" - +#include "libRepoMan/Frontend/Repo.hpp" #include "RepositoryModule.h" #include "RepoTreeView.hpp" #include "CloneRepositoryDlg.h" @@ -54,8 +53,8 @@ void RepositoryModule::initialize() mMostRecentlyUsed = configGet( "MRU", QStringList() ); - connect(&MacGitver::repoMan(), SIGNAL(repositoryOpened(RM::Repo*)), - this, SLOT(onCoreRepoOpen(RM::Repo*))); + connect(&RM::RepoMan::instance(), &RM::RepoMan::repositoryOpened, + this, &RepositoryModule::onCoreRepoOpen); updateMostRecentlyUsedMenu(); @@ -117,17 +116,8 @@ void RepositoryModule::onRepositoryOpenHelper() return; } - MacGitver::repoMan().open(repoDir); - - // ###REPOMAN This should move to an eventlistener, which is invoked by RepoMan for every - // opened repository. This will then also boost the priority in the LRU menu for - // repositories opened through it. - - // If we successfully loaded the repository at that directory, - // we store the repository's work dir as "lastUsedDir". - // If it is a bare repository, we store the repository's directory. + RM::RepoMan::instance().open(repoDir); Config::self().set("Repository/lastUsedDir", repoDir); - // repo.isBare() ? repoDir : repo.basePath() ); } void RepositoryModule::onRepositoryClone() @@ -138,17 +128,17 @@ void RepositoryModule::onRepositoryClone() void RepositoryModule::onRecentRepositoryOpen( const QVariant& path ) { QString repoPath = path.toString(); - MacGitver::repoMan().open( repoPath ); + RM::RepoMan::instance().open( repoPath ); } -void RepositoryModule::onCoreRepoOpen(RM::Repo* repo) +void RepositoryModule::onCoreRepoOpen(const RM::Frontend::Repo& repo) { - if( repo->isSubModule() ) + if( repo.isSubModule() ) { return; } - QString path = repo->path(); + QString path = repo.path(); mMostRecentlyUsed.removeAll( path ); mMostRecentlyUsed.prepend( path ); diff --git a/Modules/Repository/RepositoryModule.h b/Modules/Repository/RepositoryModule.h index ac7086b2..b46f3b88 100644 --- a/Modules/Repository/RepositoryModule.h +++ b/Modules/Repository/RepositoryModule.h @@ -26,7 +26,9 @@ namespace RM { - class Repo; + namespace Frontend { + class Repo; + } } class RepositoryModule @@ -63,7 +65,7 @@ private slots: private slots: void onRepositoryOpenHelper(); - void onCoreRepoOpen(RM::Repo* repo); + void onCoreRepoOpen(const RM::Frontend::Repo& repo); private: void updateMostRecentlyUsedMenu();