~neon/kompare/master

« back to all changes in this revision

Viewing changes to src/komparepart/komparesplitter.cpp

  • Committer: Friedrich W. H. Kossebau
  • Date: 2020-11-13 21:43:33 UTC
  • Revision ID: git-v1:79fce0df862602a8e2790d7d14f4037744a006f6
Reorganize sources into src/ subfolder

NO_CHANGELOG

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
**                              komparesplitter.cpp
 
3
**                              -------------------
 
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
***************************************************************************/
 
8
 
 
9
/**************************************************************************
 
10
**
 
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.
 
15
**
 
16
***************************************************************************/
 
17
 
 
18
// associated header
 
19
#include "komparesplitter.h"
 
20
 
 
21
// qt
 
22
#include <QStyle>
 
23
#include <QString>
 
24
#include <QTimer>
 
25
#include <QScrollBar>
 
26
#include <QMap>
 
27
#include <QSplitter>
 
28
#include <QApplication>
 
29
#include <QPainter>
 
30
#include <QPixmap>
 
31
#include <QKeyEvent>
 
32
#include <QGridLayout>
 
33
#include <QResizeEvent>
 
34
#include <QChildEvent>
 
35
#include <QEvent>
 
36
#include <QWheelEvent>
 
37
 
 
38
// kde
 
39
 
 
40
// kompare
 
41
#include "komparelistview.h"
 
42
#include "viewsettings.h"
 
43
#include "kompareconnectwidget.h"
 
44
#include <libkomparediff2/diffmodel.h>
 
45
#include <libkomparediff2/difference.h>
 
46
 
 
47
using namespace Diff2;
 
48
 
 
49
KompareSplitter::KompareSplitter(ViewSettings* settings, QWidget* parent) :
 
50
    QSplitter(Qt::Horizontal, parent),
 
51
    m_settings(settings)
 
52
{
 
53
    QFrame* scrollFrame = static_cast<QFrame*>(parent);
 
54
 
 
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);
 
65
 
 
66
    new KompareListViewFrame(true, m_settings, this, "source");
 
67
    new KompareListViewFrame(false, m_settings, this, "destination");
 
68
    pairlayout->addWidget(this, 0, 0);
 
69
 
 
70
    // set up our looks
 
71
    setLineWidth(style()->pixelMetric(QStyle::PM_DefaultFrameWidth));
 
72
 
 
73
    setHandleWidth(50);
 
74
    setChildrenCollapsible(false);
 
75
    setFrameStyle(QFrame::NoFrame);
 
76
    setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
 
77
    setOpaqueResize(true);
 
78
    setFocusPolicy(Qt::WheelFocus);
 
79
 
 
80
    connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotConfigChanged);
 
81
    connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotDelayedRepaintHandles);
 
82
    connect(this, &KompareSplitter::configChanged, this, &KompareSplitter::slotDelayedUpdateScrollBars);
 
83
 
 
84
    // scrolling
 
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);
 
89
 
 
90
    m_scrollTimer = new QTimer(this);
 
91
    m_restartTimer = false;
 
92
    connect(m_scrollTimer, &QTimer::timeout, this, &KompareSplitter::timerTimeout);
 
93
 
 
94
    // we need to receive childEvents now so that d->list is ready for when
 
95
    // slotSetSelection(...) arrives
 
96
    qApp->sendPostedEvents(this, QEvent::ChildAdded);
 
97
 
 
98
    // init stuff
 
99
    slotUpdateScrollBars();
 
100
}
 
101
 
 
102
KompareSplitter::~KompareSplitter()
 
103
{
 
104
}
 
105
 
 
106
QSplitterHandle* KompareSplitter::createHandle()
 
107
{
 
108
    return new KompareConnectWidgetFrame(m_settings, this);
 
109
}
 
110
 
 
111
void KompareSplitter::slotDelayedRepaintHandles()
 
112
{
 
113
    QTimer::singleShot(0, this, &KompareSplitter::slotRepaintHandles);
 
114
}
 
115
 
 
116
void KompareSplitter::slotRepaintHandles()
 
117
{
 
118
    const int end = count();
 
119
    for (int i = 1; i < end; ++i)
 
120
        handle(i)->update();
 
121
}
 
122
 
 
123
void KompareSplitter::timerTimeout()
 
124
{
 
125
    if (m_restartTimer)
 
126
        m_restartTimer = false;
 
127
    else
 
128
        m_scrollTimer->stop();
 
129
 
 
130
    slotDelayedRepaintHandles();
 
131
 
 
132
    Q_EMIT scrollViewsToId(m_scrollTo);
 
133
    slotRepaintHandles();
 
134
    m_vScroll->setValue(m_scrollTo);
 
135
}
 
136
 
 
137
void KompareSplitter::slotScrollToId(int id)
 
138
{
 
139
    m_scrollTo = id;
 
140
 
 
141
    if (m_restartTimer)
 
142
        return;
 
143
 
 
144
    if (m_scrollTimer->isActive())
 
145
    {
 
146
        m_restartTimer = true;
 
147
    }
 
148
    else
 
149
    {
 
150
        Q_EMIT scrollViewsToId(id);
 
151
        slotRepaintHandles();
 
152
        m_vScroll->setValue(id);
 
153
        m_scrollTimer->start(30);
 
154
    }
 
155
}
 
156
 
 
157
void KompareSplitter::slotDelayedUpdateScrollBars()
 
158
{
 
159
    QTimer::singleShot(0, this, &KompareSplitter::slotUpdateScrollBars);
 
160
}
 
161
 
 
162
void KompareSplitter::slotUpdateScrollBars()
 
163
{
 
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);
 
170
        }
 
171
    }
 
172
 
 
173
    int m_scrollDistance = m_settings->m_scrollNoOfLines * lineHeight();
 
174
    int m_pageSize = pageSize();
 
175
 
 
176
    if (needVScrollBar())
 
177
    {
 
178
        m_vScroll->show();
 
179
 
 
180
        m_vScroll->blockSignals(true);
 
181
        m_vScroll->setRange(minVScrollId(),
 
182
                            maxVScrollId());
 
183
        m_vScroll->setValue(scrollId());
 
184
        m_vScroll->setSingleStep(m_scrollDistance);
 
185
        m_vScroll->setPageStep(m_pageSize);
 
186
        m_vScroll->blockSignals(false);
 
187
    }
 
188
    else
 
189
    {
 
190
        m_vScroll->hide();
 
191
    }
 
192
 
 
193
    if (needHScrollBar())
 
194
    {
 
195
        m_hScroll->show();
 
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);
 
202
    }
 
203
    else
 
204
    {
 
205
        m_hScroll->hide();
 
206
    }
 
207
}
 
208
 
 
209
void KompareSplitter::slotDelayedUpdateVScrollValue()
 
210
{
 
211
    QTimer::singleShot(0, this, &KompareSplitter::slotUpdateVScrollValue);
 
212
}
 
213
 
 
214
void KompareSplitter::slotUpdateVScrollValue()
 
215
{
 
216
    m_vScroll->setValue(scrollId());
 
217
}
 
218
 
 
219
void KompareSplitter::keyPressEvent(QKeyEvent* e)
 
220
{
 
221
    //keyboard scrolling
 
222
    switch (e->key()) {
 
223
    case Qt::Key_Right:
 
224
    case Qt::Key_L:
 
225
        m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd);
 
226
        break;
 
227
    case Qt::Key_Left:
 
228
    case Qt::Key_H:
 
229
        m_hScroll->triggerAction(QAbstractSlider::SliderSingleStepSub);
 
230
        break;
 
231
    case Qt::Key_Up:
 
232
    case Qt::Key_K:
 
233
        m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepSub);
 
234
        break;
 
235
    case Qt::Key_Down:
 
236
    case Qt::Key_J:
 
237
        m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd);
 
238
        break;
 
239
    case Qt::Key_PageDown:
 
240
        m_vScroll->triggerAction(QAbstractSlider::SliderPageStepAdd);
 
241
        break;
 
242
    case Qt::Key_PageUp:
 
243
        m_vScroll->triggerAction(QAbstractSlider::SliderPageStepSub);
 
244
        break;
 
245
    }
 
246
    e->accept();
 
247
    slotRepaintHandles();
 
248
}
 
249
 
 
250
void KompareSplitter::wheelEvent(QWheelEvent* e)
 
251
{
 
252
    if (e->angleDelta().y() != 0)
 
253
    {
 
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);
 
259
        } else {
 
260
            if (e->angleDelta().y() < 0)   // scroll down
 
261
                m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepAdd);
 
262
            else // scroll up
 
263
                m_vScroll->triggerAction(QAbstractSlider::SliderSingleStepSub);
 
264
        }
 
265
    }
 
266
    else
 
267
    {
 
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);
 
273
        } else {
 
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);
 
278
        }
 
279
    }
 
280
    e->accept();
 
281
    slotDelayedRepaintHandles();
 
282
}
 
283
 
 
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.
 
286
 */
 
287
 
 
288
int KompareSplitter::scrollId()
 
289
{
 
290
    if (widget(0))
 
291
        return listView(0)->scrollId();
 
292
    return minVScrollId();
 
293
}
 
294
 
 
295
int KompareSplitter::lineHeight()
 
296
{
 
297
    if (widget(0))
 
298
        return listView(0)->fontMetrics().height();
 
299
    return 1;
 
300
}
 
301
 
 
302
int KompareSplitter::pageSize()
 
303
{
 
304
    if (widget(0)) {
 
305
        KompareListView* view = listView(0);
 
306
        return view->visibleHeight() - view->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
 
307
    }
 
308
    return 1;
 
309
}
 
310
 
 
311
bool KompareSplitter::needVScrollBar()
 
312
{
 
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)
 
318
            return true;
 
319
    }
 
320
    return false;
 
321
}
 
322
 
 
323
int KompareSplitter::minVScrollId()
 
324
{
 
325
 
 
326
    int min = -1;
 
327
    int mSId;
 
328
    const int end = count();
 
329
    for (int i = 0; i < end; ++i) {
 
330
        mSId = listView(i)->minScrollId();
 
331
        if (mSId < min || min == -1)
 
332
            min = mSId;
 
333
    }
 
334
    return (min == -1) ? 0 : min;
 
335
}
 
336
 
 
337
int KompareSplitter::maxVScrollId()
 
338
{
 
339
    int max = 0;
 
340
    int mSId;
 
341
    const int end = count();
 
342
    for (int i = 0; i < end; ++i) {
 
343
        mSId = listView(i)->maxScrollId();
 
344
        if (mSId > max)
 
345
            max = mSId;
 
346
    }
 
347
    return max;
 
348
}
 
349
 
 
350
bool KompareSplitter::needHScrollBar()
 
351
{
 
352
    const int end = count();
 
353
    for (int i = 0; i < end; ++i) {
 
354
        KompareListView* view = listView(i);
 
355
        if (view->contentsWidth() > view->visibleWidth())
 
356
            return true;
 
357
    }
 
358
    return false;
 
359
}
 
360
 
 
361
int KompareSplitter::minHScrollId()
 
362
{
 
363
    // hardcode an offset to hide the tree controls
 
364
    return 6;
 
365
}
 
366
 
 
367
int KompareSplitter::maxHScrollId()
 
368
{
 
369
    int max = 0;
 
370
    int mHSId;
 
371
    const int end = count();
 
372
    for (int i = 0; i < end; ++i) {
 
373
        KompareListView* view = listView(i);
 
374
        mHSId = view->contentsWidth() - view->visibleWidth();
 
375
        if (mHSId > max)
 
376
            max = mHSId;
 
377
    }
 
378
    return max;
 
379
}
 
380
 
 
381
int KompareSplitter::maxContentsX()
 
382
{
 
383
    int max = 0;
 
384
    int mCX;
 
385
    const int end = count();
 
386
    for (int i = 0; i < end; ++i) {
 
387
        mCX = listView(i)->contentsX();
 
388
        if (mCX > max)
 
389
            max = mCX;
 
390
    }
 
391
    return max;
 
392
}
 
393
 
 
394
int KompareSplitter::minVisibleWidth()
 
395
{
 
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
 
401
    int min = -1;
 
402
    int vW;
 
403
    const int end = count();
 
404
    for (int i = 0; i < end; ++i) {
 
405
        vW = listView(i)->visibleWidth();
 
406
        if (vW < min || min == -1)
 
407
            min = vW;
 
408
    }
 
409
    return (min == -1) ? 0 : min;
 
410
}
 
411
 
 
412
KompareListView* KompareSplitter::listView(int index)
 
413
{
 
414
    return static_cast<KompareListViewFrame*>(widget(index))->view();
 
415
}
 
416
 
 
417
KompareConnectWidget* KompareSplitter::connectWidget(int index)
 
418
{
 
419
    return static_cast<KompareConnectWidgetFrame*>(handle(index))->wid();
 
420
}
 
421
 
 
422
void KompareSplitter::slotSetSelection(const DiffModel* model, const Difference* diff)
 
423
{
 
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);
 
429
    }
 
430
 
 
431
    slotDelayedRepaintHandles();
 
432
    slotDelayedUpdateScrollBars();
 
433
}
 
434
 
 
435
void KompareSplitter::slotSetSelection(const Difference* diff)
 
436
{
 
437
    const int end = count();
 
438
    for (int i = 0; i < end; ++i) {
 
439
        connectWidget(i)->slotSetSelection(diff);
 
440
        listView(i)->slotSetSelection(diff);
 
441
    }
 
442
 
 
443
    slotDelayedRepaintHandles();
 
444
    slotDelayedUpdateScrollBars();
 
445
}
 
446
 
 
447
void KompareSplitter::slotApplyDifference(bool apply)
 
448
{
 
449
    const int end = count();
 
450
    for (int i = 0; i < end; ++i)
 
451
        listView(i)->slotApplyDifference(apply);
 
452
    slotDelayedRepaintHandles();
 
453
}
 
454
 
 
455
void KompareSplitter::slotApplyAllDifferences(bool apply)
 
456
{
 
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!
 
462
}
 
463
 
 
464
void KompareSplitter::slotApplyDifference(const Difference* diff, bool apply)
 
465
{
 
466
    const int end = count();
 
467
    for (int i = 0; i < end; ++i)
 
468
        listView(i)->slotApplyDifference(diff, apply);
 
469
    slotDelayedRepaintHandles();
 
470
}
 
471
 
 
472
void KompareSplitter::slotDifferenceClicked(const Difference* diff)
 
473
{
 
474
    const int end = count();
 
475
    for (int i = 0; i < end; ++i)
 
476
        listView(i)->setSelectedDifference(diff, false);
 
477
    Q_EMIT selectionChanged(diff);
 
478
}
 
479
 
 
480
void KompareSplitter::slotConfigChanged()
 
481
{
 
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);
 
486
        view->update();
 
487
    }
 
488
}