1
/**************************************************************************
4
** begin : Wed Jan 14 2004
5
** Copyright 2004-2005 Jeff Snyder <jeff-webcvsspam@caffeinated.me.uk>
6
** Copyright 2007-2011 Kevin Kofler <kevin.kofler@chello.at>
7
***************************************************************************/
9
/**************************************************************************
11
** This program is free software; you can redistribute it and/or modify
12
** it under the terms of the GNU General Public License as published by
13
** the Free Software Foundation; either version 2 of the License, or
14
** (at your option) any later version.
16
***************************************************************************/
19
#include "komparesplitter.h"
28
#include <QApplication>
32
#include <QGridLayout>
33
#include <QResizeEvent>
34
#include <QChildEvent>
36
#include <QWheelEvent>
41
#include "komparelistview.h"
42
#include "viewsettings.h"
43
#include "kompareconnectwidget.h"
44
#include <libkomparediff2/diffmodel.h>
45
#include <libkomparediff2/difference.h>
47
using namespace Diff2;
49
KompareSplitter::KompareSplitter(ViewSettings* settings, QWidget* parent) :
50
QSplitter(Qt::Horizontal, parent),
53
QFrame* scrollFrame = static_cast<QFrame*>(parent);
55
// Set up the scrollFrame
56
scrollFrame->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
57
scrollFrame->setLineWidth(scrollFrame->style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
58
QGridLayout* pairlayout = new QGridLayout(scrollFrame);
59
pairlayout->setSpacing(0);
60
pairlayout->setContentsMargins(0, 0, 0, 0);
61
m_vScroll = new QScrollBar(Qt::Vertical, scrollFrame);
62
pairlayout->addWidget(m_vScroll, 0, 1);
63
m_hScroll = new QScrollBar(Qt::Horizontal, scrollFrame);
64
pairlayout->addWidget(m_hScroll, 1, 0);
66
new KompareListViewFrame(true, m_settings, this, "source");
67
new KompareListViewFrame(false, m_settings, this, "destination");
68
pairlayout->addWidget(this, 0, 0);
71
setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
74
setChildrenCollapsible(false);
75
setFrameStyle(QFrame::NoFrame);
76
setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
77
setOpaqueResize(true);
78
setFocusPolicy(Qt::WheelFocus);
80
connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotConfigChanged);
81
connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotDelayedRepaintHandles);
82
connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotDelayedUpdateScrollBars);
85
connect(m_vScroll, &QScrollBar::valueChanged, this, &KompareSplitter::slotScrollToId);
86
connect(m_vScroll, &QScrollBar::sliderMoved, this, &KompareSplitter::slotScrollToId);
87
connect(m_hScroll, &QScrollBar::valueChanged, this, &KompareSplitter::setXOffset);
88
connect(m_hScroll, &QScrollBar::sliderMoved, this, &KompareSplitter::setXOffset);
90
m_scrollTimer = new QTimer(this);
91
m_restartTimer = false;
92
connect(m_scrollTimer, &QTimer::timeout, this, &KompareSplitter::timerTimeout);
94
// we need to receive childEvents now so that d->list is ready for when
95
// slotSetSelection(...) arrives
96
qApp->sendPostedEvents(this, QEvent::ChildAdded);
99
slotUpdateScrollBars();
102
KompareSplitter::~KompareSplitter()
106
QSplitterHandle* KompareSplitter::createHandle()
108
return new KompareConnectWidgetFrame(m_settings, this);
111
void KompareSplitter::slotDelayedRepaintHandles()
113
QTimer::singleShot(0, this, &KompareSplitter::slotRepaintHandles);
116
void KompareSplitter::slotRepaintHandles()
118
const int end = count();
119
for (int i = 1; i < end; ++i)
123
void KompareSplitter::timerTimeout()
126
m_restartTimer = false;
128
m_scrollTimer->stop();
130
slotDelayedRepaintHandles();
132
Q_EMIT scrollViewsToId(m_scrollTo);
133
slotRepaintHandles();
134
m_vScroll->setValue(m_scrollTo);
137
void KompareSplitter::slotScrollToId(int id)
144
if (m_scrollTimer->isActive())
146
m_restartTimer = true;
150
Q_EMIT scrollViewsToId(id);
151
slotRepaintHandles();
152
m_vScroll->setValue(id);
153
m_scrollTimer->start(30);
157
void KompareSplitter::slotDelayedUpdateScrollBars()
159
QTimer::singleShot(0, this, &KompareSplitter::slotUpdateScrollBars);
162
void KompareSplitter::slotUpdateScrollBars()
164
const int end = count();
165
for (int i = 0; i < end; ++i) {
166
KompareListView* lv = listView(i);
167
int minHScroll = minHScrollId();
168
if (lv->contentsX() < minHScroll) {
169
lv->setXOffset(minHScroll);
173
int m_scrollDistance = m_settings->m_scrollNoOfLines * lineHeight();
174
int m_pageSize = pageSize();
176
if (needVScrollBar())
180
m_vScroll->blockSignals(true);
181
m_vScroll->setRange(minVScrollId(),
183
m_vScroll->setValue(scrollId());
184
m_vScroll->setSingleStep(m_scrollDistance);
185
m_vScroll->setPageStep(m_pageSize);
186
m_vScroll->blockSignals(false);
193
if (needHScrollBar())
196
m_hScroll->blockSignals(true);
197
m_hScroll->setRange(minHScrollId(), maxHScrollId());
198
m_hScroll->setValue(maxContentsX());
199
m_hScroll->setSingleStep(10);
200
m_hScroll->setPageStep(minVisibleWidth() - 10);
201
m_hScroll->blockSignals(false);
209
void KompareSplitter::slotDelayedUpdateVScrollValue()
211
QTimer::singleShot(0, this, &KompareSplitter::slotUpdateVScrollValue);
214
void KompareSplitter::slotUpdateVScrollValue()
216
m_vScroll->setValue(scrollId());
219
void KompareSplitter::keyPressEvent(QKeyEvent* e)
225
m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd);
229
m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepSub);
233
m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepSub);
237
m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd);
239
case Qt::Key_PageDown:
240
m_vScroll->triggerAction(QAbstractSlider::SliderPageStepAdd);
243
m_vScroll->triggerAction(QAbstractSlider::SliderPageStepSub);
247
slotRepaintHandles();
250
void KompareSplitter::wheelEvent(QWheelEvent* e)
252
if (e->angleDelta().y() != 0)
254
if (e->modifiers() & Qt::ControlModifier) {
255
if (e->angleDelta().y() < 0) // scroll down one page
256
m_vScroll->triggerAction(QAbstractSlider::SliderPageStepAdd);
257
else // scroll up one page
258
m_vScroll->triggerAction(QAbstractSlider::SliderPageStepSub);
260
if (e->angleDelta().y() < 0) // scroll down
261
m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd);
263
m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepSub);
268
if (e->modifiers() & Qt::ControlModifier) {
269
if (e->angleDelta().y() < 0) // scroll right one page
270
m_hScroll->triggerAction(QAbstractSlider::SliderPageStepAdd);
271
else // scroll left one page
272
m_hScroll->triggerAction(QAbstractSlider::SliderPageStepSub);
274
if (e->angleDelta().y() < 0) // scroll to the right
275
m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd);
276
else // scroll to the left
277
m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepSub);
281
slotDelayedRepaintHandles();
284
/* FIXME: this should return/the scrollId() from the listview containing the
285
* /base/ of the diff. but there's bigger issues with that atm.
288
int KompareSplitter::scrollId()
291
return listView(0)->scrollId();
292
return minVScrollId();
295
int KompareSplitter::lineHeight()
298
return listView(0)->fontMetrics().height();
302
int KompareSplitter::pageSize()
305
KompareListView* view = listView(0);
306
return view->visibleHeight() - view->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
311
bool KompareSplitter::needVScrollBar()
313
int pagesize = pageSize();
314
const int end = count();
315
for (int i = 0; i < end; ++i) {
316
KompareListView* view = listView(i);
317
if (view ->contentsHeight() > pagesize)
323
int KompareSplitter::minVScrollId()
328
const int end = count();
329
for (int i = 0; i < end; ++i) {
330
mSId = listView(i)->minScrollId();
331
if (mSId < min || min == -1)
334
return (min == -1) ? 0 : min;
337
int KompareSplitter::maxVScrollId()
341
const int end = count();
342
for (int i = 0; i < end; ++i) {
343
mSId = listView(i)->maxScrollId();
350
bool KompareSplitter::needHScrollBar()
352
const int end = count();
353
for (int i = 0; i < end; ++i) {
354
KompareListView* view = listView(i);
355
if (view->contentsWidth() > view->visibleWidth())
361
int KompareSplitter::minHScrollId()
363
// hardcode an offset to hide the tree controls
367
int KompareSplitter::maxHScrollId()
371
const int end = count();
372
for (int i = 0; i < end; ++i) {
373
KompareListView* view = listView(i);
374
mHSId = view->contentsWidth() - view->visibleWidth();
381
int KompareSplitter::maxContentsX()
385
const int end = count();
386
for (int i = 0; i < end; ++i) {
387
mCX = listView(i)->contentsX();
394
int KompareSplitter::minVisibleWidth()
396
// Why the hell do we want to know this?
397
// ah yes, it is because we use it to set the "page size" for horiz. scrolling.
398
// despite the fact that *none* has a pgright and pgleft key :P
399
// But we do have mousewheels with horizontal scrolling functionality,
400
// pressing shift and scrolling then goes left and right one page at the time
403
const int end = count();
404
for (int i = 0; i < end; ++i) {
405
vW = listView(i)->visibleWidth();
406
if (vW < min || min == -1)
409
return (min == -1) ? 0 : min;
412
KompareListView* KompareSplitter::listView(int index)
414
return static_cast<KompareListViewFrame*>(widget(index))->view();
417
KompareConnectWidget* KompareSplitter::connectWidget(int index)
419
return static_cast<KompareConnectWidgetFrame*>(handle(index))->wid();
422
void KompareSplitter::slotSetSelection(const DiffModel* model, const Difference* diff)
424
const int end = count();
425
for (int i = 0; i < end; ++i) {
426
connectWidget(i)->slotSetSelection(model, diff);
427
listView(i)->slotSetSelection(model, diff);
428
static_cast<KompareListViewFrame*>(widget(i))->slotSetModel(model);
431
slotDelayedRepaintHandles();
432
slotDelayedUpdateScrollBars();
435
void KompareSplitter::slotSetSelection(const Difference* diff)
437
const int end = count();
438
for (int i = 0; i < end; ++i) {
439
connectWidget(i)->slotSetSelection(diff);
440
listView(i)->slotSetSelection(diff);
443
slotDelayedRepaintHandles();
444
slotDelayedUpdateScrollBars();
447
void KompareSplitter::slotApplyDifference(bool apply)
449
const int end = count();
450
for (int i = 0; i < end; ++i)
451
listView(i)->slotApplyDifference(apply);
452
slotDelayedRepaintHandles();
455
void KompareSplitter::slotApplyAllDifferences(bool apply)
457
const int end = count();
458
for (int i = 0; i < end; ++i)
459
listView(i)->slotApplyAllDifferences(apply);
460
slotDelayedRepaintHandles();
461
slotScrollToId(m_scrollTo); // FIXME!
464
void KompareSplitter::slotApplyDifference(const Difference* diff, bool apply)
466
const int end = count();
467
for (int i = 0; i < end; ++i)
468
listView(i)->slotApplyDifference(diff, apply);
469
slotDelayedRepaintHandles();
472
void KompareSplitter::slotDifferenceClicked(const Difference* diff)
474
const int end = count();
475
for (int i = 0; i < end; ++i)
476
listView(i)->setSelectedDifference(diff, false);
477
Q_EMIT selectionChanged(diff);
480
void KompareSplitter::slotConfigChanged()
482
const int end = count();
483
for (int i = 0; i < end; ++i) {
484
KompareListView* view = listView(i);
485
view->setFont(m_settings->m_font);