Index: plugins/bazaar/bazaarplugin.cpp =================================================================== --- plugins/bazaar/bazaarplugin.cpp +++ plugins/bazaar/bazaarplugin.cpp @@ -115,6 +115,7 @@ VcsJob* BazaarPlugin::diff(const QUrl& fileOrDirectory, const VcsRevision& srcRevision, const VcsRevision& dstRevision, VcsDiff::Type, IBasicVersionControl::RecursionMode recursion) { Q_UNUSED(recursion); + // TODO support m_contextLines (less urgent because Phabricator doesn't support Bazaar) VcsJob* job = new DiffJob(BazaarUtils::workingCopy(fileOrDirectory), BazaarUtils::getRevisionSpecRange(srcRevision, dstRevision), fileOrDirectory, this); return job; } Index: plugins/cvs/cvsplugin.h =================================================================== --- plugins/cvs/cvsplugin.h +++ plugins/cvs/cvsplugin.h @@ -74,7 +74,7 @@ KDevelop::VcsJob* diff(const QUrl& fileOrDirectory, const KDevelop::VcsRevision& srcRevision, const KDevelop::VcsRevision& dstRevision, - KDevelop::VcsDiff::Type, + KDevelop::VcsDiff::Type=KDevelop::VcsDiff::DiffUnified, KDevelop::IBasicVersionControl::RecursionMode = KDevelop::IBasicVersionControl::Recursive) override; KDevelop::VcsJob* log(const QUrl& localLocation, const KDevelop::VcsRevision& rev, Index: plugins/cvs/cvsplugin.cpp =================================================================== --- plugins/cvs/cvsplugin.cpp +++ plugins/cvs/cvsplugin.cpp @@ -388,7 +388,8 @@ KDevelop::VcsJob * CvsPlugin::diff(const QUrl & fileOrDirectory, const KDevelop::VcsRevision & srcRevision, const KDevelop::VcsRevision & dstRevision, KDevelop::VcsDiff::Type, KDevelop::IBasicVersionControl::RecursionMode) { - CvsJob* job = d->m_proxy->diff(fileOrDirectory, srcRevision, dstRevision, QStringLiteral("-uN")/*always unified*/); + QString options = m_contextLines > 0? QStringLiteral("-uN -context=%1").arg(m_contextLines) : QStringLiteral("-uN")/*always unified*/; + CvsJob* job = d->m_proxy->diff(fileOrDirectory, srcRevision, dstRevision, options); return job; } Index: plugins/git/gitplugin.cpp =================================================================== --- plugins/git/gitplugin.cpp +++ plugins/git/gitplugin.cpp @@ -351,12 +351,15 @@ DVcsJob* job = new GitJob(dotGitDirectory(fileOrDirectory), this, KDevelop::OutputJob::Silent); job->setType(VcsJob::Diff); - *job << "git" << "diff" << "--no-color" << "--no-ext-diff"; + *job << "git" << "diff" << "--no-color" << "--no-ext-diff" << "--full-index"; if (!usePrefix()) { // KDE's ReviewBoard now requires p1 patchfiles, so `git diff --no-prefix` to generate p0 patches // has become optional. *job << "--no-prefix"; } + if (m_contextLines > 0) { + *job << QStringLiteral("-U%1").arg(m_contextLines); + } if (dstRevision.revisionType() == VcsRevision::Special && dstRevision.specialType() == VcsRevision::Working) { if (srcRevision.revisionType() == VcsRevision::Special && Index: plugins/patchreview/patchreview.h =================================================================== --- plugins/patchreview/patchreview.h +++ plugins/patchreview/patchreview.h @@ -100,6 +100,7 @@ void highlightPatch(); void updateKompareModel(); void forceUpdate(); + void forceUpdateWithContext(int contextLines); void areaChanged(Sublime::Area* area); void executeFileReviewAction(); Index: plugins/patchreview/patchreview.cpp =================================================================== --- plugins/patchreview/patchreview.cpp +++ plugins/patchreview/patchreview.cpp @@ -223,6 +223,17 @@ } } +void PatchReviewPlugin::forceUpdateWithContext(int contextLines) { + if( m_patch ) { + // register the requested number of lines of context + // and regenerate the patch. + m_patch->setContextLines(contextLines); + m_patch->update(); + + notifyPatchChanged(); + } +} + void PatchReviewPlugin::updateKompareModel() { if ( !m_patch ) { ///TODO: this method should be cleaned up, it can be called by the timer and Index: plugins/patchreview/patchreview.ui =================================================================== --- plugins/patchreview/patchreview.ui +++ plugins/patchreview/patchreview.ui @@ -72,13 +72,39 @@ + + + lines of context for the unified diff + + + max + + + + + + 0 + + + 999 + + + 3 + + + + 0 0 + + Click to update the patch +Right-click to select the number of lines of context the patch should show. + Update Index: plugins/patchreview/patchreviewtoolview.h =================================================================== --- plugins/patchreview/patchreviewtoolview.h +++ plugins/patchreview/patchreviewtoolview.h @@ -32,6 +32,7 @@ class LocalPatchSource; class QModelIndex; class QSortFilterProxyModel; +class DiffContextMenu; class PatchReviewToolView : public QWidget { @@ -103,6 +104,8 @@ class PatchFilesModel* m_fileModel; QSortFilterProxyModel* m_fileSortProxyModel; + DiffContextMenu *m_diffContextMenu; + public slots: void documentActivated( KDevelop::IDocument* ); void customContextMenuRequested(const QPoint& p); Index: plugins/patchreview/patchreviewtoolview.cpp =================================================================== --- plugins/patchreview/patchreviewtoolview.cpp +++ plugins/patchreview/patchreviewtoolview.cpp @@ -39,6 +39,11 @@ #include #include +#include +#include +#include +#include + #include #include #include @@ -51,6 +56,76 @@ using namespace KDevelop; +class DiffContextMenu : public QObject +{ + Q_OBJECT +public: + DiffContextMenu(PatchReviewPlugin *prPlugin) + : QObject(dynamic_cast(prPlugin)) + , m_prPlugin(prPlugin) + { + m_contextActions = new QActionGroup(this); + m_contextActions->setExclusive(true); + QAction *title = new QAction(i18n("diff context"), m_contextActions); + title->setEnabled(false); + m_contextActions->addAction(title); + for (int i = 1; i <= 5; ++i) { + addContextAction(i); + } + addContextAction(10); + addContextAction(0); + } + + void addContextAction(int contextLines) + { + QAction *action; + if (contextLines == 0) { + action = new QAction(i18n("whole file"), m_contextActions); + } else if (contextLines > 0) { + action = new QAction(i18n("%1 lines").arg(contextLines), m_contextActions); + } else { + return; + } + action->setData(contextLines); + action->setCheckable(true); + connect(action, &QAction::triggered, this, [action, this]() { + action->setChecked(true); + m_prPlugin->forceUpdateWithContext(action->data().toInt()); + }); + m_contextActions->addAction(action); + if (contextLines == 3) { + m_defaultContextAction = action; + action->setChecked(true); + } + } + + bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE + { + if (event->type() == QEvent::Gesture) { + QGestureEvent *gEvent = static_cast(event); + if (QTapAndHoldGesture *heldTap = static_cast(gEvent->gesture(Qt::TapAndHoldGesture))) { + if (heldTap->state() == Qt::GestureFinished) { + QPushButton *btn = dynamic_cast(obj); + if (btn) { + // user clicked and held a widget, send it a simulated ContextMenuEvent: + QContextMenuEvent ce(QContextMenuEvent::Mouse, heldTap->position().toPoint(), + heldTap->hotSpot().toPoint()); + gEvent->accept(); + int ret = QCoreApplication::sendEvent(btn, &ce); + btn->setDown(false); + return ret; + } + } + } + } + return false; + } + + QActionGroup *m_contextActions; + PatchReviewPlugin *m_prPlugin; + QAction *m_defaultContextAction; +}; + class PatchFilesModel : public VcsFileChangesModel { Q_OBJECT @@ -126,6 +201,12 @@ } void PatchReviewToolView::patchChanged() { + if(m_resetCheckedUrls) { + // set the default number of context lines + m_editPatch.diffContext->setValue(3); + m_diffContextMenu->m_defaultContextAction->setChecked(true); + } + fillEditFromPatch(); kompareModelChanged(); @@ -251,6 +332,16 @@ //connect( this, SIGNAL(finished(int)), this, SLOT(slotEditDialogFinished(int)) ); connect( m_editPatch.updateButton, &QPushButton::clicked, m_plugin, &PatchReviewPlugin::forceUpdate ); + m_editPatch.updateButton->setContextMenuPolicy(Qt::ActionsContextMenu); + m_diffContextMenu = new DiffContextMenu(m_plugin); + m_editPatch.updateButton->addActions(m_diffContextMenu->m_contextActions->actions()); + // make it possible to open the context menu with a click-and-hold: + m_editPatch.updateButton->installEventFilter(m_diffContextMenu); + m_editPatch.updateButton->grabGesture(Qt::TapAndHoldGesture); + // FIXME: cleanup after deciding on the GUI + m_editPatch.diffContext->hide(); +// connect( m_editPatch.diffContext, static_cast(&QSpinBox::valueChanged), +// m_plugin, &PatchReviewPlugin::forceUpdateWithContext ); connect( m_editPatch.testsButton, &QPushButton::clicked, this, &PatchReviewToolView::runTests ); Index: plugins/perforce/perforceplugin.cpp =================================================================== --- plugins/perforce/perforceplugin.cpp +++ plugins/perforce/perforceplugin.cpp @@ -321,7 +321,11 @@ case VcsRevision::Special: switch (dstRevision.revisionValue().value()) { case VcsRevision::Working: - *job << m_perforceExecutable << "diff" << "-du" << depotSrcFileName; + if (m_contextLines > 0) { + *job << m_perforceExecutable << "diff" << "-dU" << QString::number(m_contextLines) << depotSrcFileName; + } else { + *job << m_perforceExecutable << "diff" << "-du" << depotSrcFileName; + } break; case VcsRevision::Start: case VcsRevision::UserSpecialType: Index: plugins/subversion/kdevsvnplugin.cpp =================================================================== --- plugins/subversion/kdevsvnplugin.cpp +++ plugins/subversion/kdevsvnplugin.cpp @@ -234,6 +234,7 @@ KDevelop::VcsDiff::Type diffType, KDevelop::IBasicVersionControl::RecursionMode recurse) { + // TODO: support custom context lines in SvnDiffJob SvnDiffJob* job = new SvnDiffJob(this); job->setSource(src); job->setDestination(dst); Index: vcs/interfaces/ibasicversioncontrol.h =================================================================== --- vcs/interfaces/ibasicversioncontrol.h +++ vcs/interfaces/ibasicversioncontrol.h @@ -174,9 +174,20 @@ RecursionMode recursion = IBasicVersionControl::Recursive ) = 0; /** + * change the number of lines of context the patch generated by diff() should show + * + * May not be supported by all VCS plugins. + * @param contextLines The number of context lines included before and after each + * hunk in a unified diff. Special values are -1 for the VCS default (usually 3) + * and 0 for the largest possible value (intended to include the whole file as context). + */ + virtual void setDiffContextLines(int contextLines) { m_contextLines = contextLines == 0 ? INT_MAX : contextLines; } + + /** * Retrieves a diff between two revisions of a file * - * The diff is in unified diff format for text files by default + * The diff is in unified diff format for text files by default and may + * use the context size set through setDiffContextLines. */ virtual VcsJob* diff( const QUrl& fileOrDirectory, const VcsRevision& srcRevision, @@ -258,6 +269,8 @@ * The default implementation does nothing. */ virtual void setupCommitMessageEditor(const QUrl&, KTextEdit* edit) const; +protected: + int m_contextLines = -1; }; } Index: vcs/interfaces/ipatchsource.h =================================================================== --- vcs/interfaces/ipatchsource.h +++ vcs/interfaces/ipatchsource.h @@ -48,6 +48,9 @@ ///should re-compare the files or whatever needs to be done ///If the patch has changed, patchChanged needs to be emitted virtual void update() = 0; + ///change the number of lines of context the patch should show + ///virtual so it can be overridden, for instance to call update(). + virtual void setContextLines(int contextLines) { m_contextLines = contextLines; } ///Name of the patch file virtual QUrl file() const = 0; @@ -91,6 +94,8 @@ Q_SIGNALS: ///Should be emitted whenever the patch has changed. void patchChanged(); + protected: + int m_contextLines = -1; }; class KDEVPLATFORMVCS_EXPORT IPatchReview Index: vcs/widgets/vcsdiffpatchsources.h =================================================================== --- vcs/widgets/vcsdiffpatchsources.h +++ vcs/widgets/vcsdiffpatchsources.h @@ -45,6 +45,13 @@ virtual KDevelop::VcsDiff update() const = 0; virtual KDevelop::IBasicVersionControl* vcs() const = 0; virtual QUrl url() const = 0; + void setContextLines(int n) + { + m_contextLines = n; + } + int contextLines() { return m_contextLines; } +protected: + int m_contextLines=-1; }; class KDEVPLATFORMVCS_EXPORT VCSStandardDiffUpdater : public VCSDiffUpdater { Index: vcs/widgets/vcsdiffpatchsources.cpp =================================================================== --- vcs/widgets/vcsdiffpatchsources.cpp +++ vcs/widgets/vcsdiffpatchsources.cpp @@ -207,6 +207,7 @@ void VCSDiffPatchSource::update() { if(!m_updater) return; + m_updater->setContextLines(m_contextLines == 0? INT_MAX : m_contextLines); updateFromDiff(m_updater->update()); } @@ -295,6 +296,7 @@ VcsDiff VCSStandardDiffUpdater::update() const { + m_vcs->setDiffContextLines(m_contextLines); QScopedPointer diffJob(m_vcs->diff(m_url, KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Base), KDevelop::VcsRevision::createSpecialRevision(KDevelop::VcsRevision::Working)));