On Monday 01 November 2004 14:19, Chris Cannam wrote:
> I think the problem with all this is that we probably shouldn't be using
> the mouse move events to handle scrolling at all, because of course we
> want autoscroll to happen whether the mouse is moving or not -- we
> should probably just make it depend on the mouse position.

That's also my conclusion after 3 days of trying to improve the current 
version (main annoyance being that once auto-scrolling starts, it occurs no 
matter how you move the mouse).

Anyway, I have to dash off so this is just a quick reply, but what you 
describe looks quite a lot like the drag auto scroll which QScrollView 
already implements. Problem being that it's behind private methods and is 
triggered on drag events, not mouse moves. However, could you give a try to 
the attached piece of code ? Don't mind the bottom widget stuff, I reused a 
test I did for the horiz. scrollbar hack we have. The only relevant bits are 
the contentsMouse(Press|Release|Move)Event() methods. Try click and drag in 
the canvas, see how it behaves. Perhaps with some tweaks it could be made to 
behave like you describe.

-- 
                                                Guillaume.
                                                http://www.telegraph-road.org
#include <qpixmap.h>
#include <qlabel.h>
#define private protected
#include <qcanvas.h>
#undef private
#include <qapplication.h>
#include <qmainwindow.h>
#include <qvbox.h>
#include <qframe.h>
#include <qlayout.h>
#include <iostream>

class MyScrollView : public QCanvasView
{
public:

    MyScrollView(QCanvas*, QWidget *parent, const char* name = 0, WFlags f = 0);

    void stuffCanvas();
    void setBottomFixedWidget(QWidget*);

protected:
    virtual void polish();
    virtual void setHBarGeometry(QScrollBar &hbar, int x, int y, int w, int h);
    virtual void contentsMouseDoubleClickEvent(QMouseEvent *e);
    virtual void contentsMouseMoveEvent(QMouseEvent *e);
    virtual void contentsMousePressEvent(QMouseEvent *e);
    virtual void contentsMouseReleaseEvent(QMouseEvent *e);
    
    void updateBottomWidgetGeometry();
    
    virtual void resizeEvent(QResizeEvent*);
    
    QWidget* m_bottomWidget;
    int m_labelNumber;
    int m_prevX;
    int m_prevY;
};

MyScrollView::MyScrollView(QCanvas* c, QWidget *parent, const char* name, WFlags f)
    : QCanvasView(c, parent, name, f),
      m_bottomWidget(0),
      m_labelNumber(0),
      m_prevX(0),
      m_prevY(0)
{
    stuffCanvas();

    canvas()->update();
    setDragAutoScroll(true);
    setAcceptDrops(true);
}

void MyScrollView::stuffCanvas()
{
    QCanvasRectangle* r = new QCanvasRectangle(10, 10, 100, 100, canvas());
    r->setPen(red);
    r->setBrush(red);
    r->show();
}

void MyScrollView::setBottomFixedWidget(QWidget* w)
{
    m_bottomWidget = w;
    m_bottomWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    updateBottomWidgetGeometry();
}

void MyScrollView::resizeEvent(QResizeEvent* e)
{
    QCanvasView::resizeEvent(e);
    if (!horizontalScrollBar()->isVisible())
        updateBottomWidgetGeometry();
    
}

void MyScrollView::polish()
{
    updateBottomWidgetGeometry();
}

void MyScrollView::setHBarGeometry(QScrollBar &hbar, int x, int y, int w, int h)
{
    QCanvasView::setHBarGeometry(hbar, x, y, w, h);
    updateBottomWidgetGeometry();
}

void MyScrollView::contentsMousePressEvent(QMouseEvent* e)
{
    startDragAutoScroll();
}

void MyScrollView::contentsMouseReleaseEvent(QMouseEvent* e)
{
    stopDragAutoScroll();
}

void MyScrollView::contentsMouseDoubleClickEvent(QMouseEvent*)
{
    std::cerr << "MyScrollView::contentsMouseDoubleClickEvent : " << m_labelNumber << std::endl;

    QLabel* l = new QLabel(QString("Label %1").arg(m_labelNumber++), m_bottomWidget);
    l->show();
    updateBottomWidgetGeometry();
    
//     m_bottomWidget->updateGeometry();
//     m_bottomWidget->layout()->invalidate();
}

void MyScrollView::contentsMouseMoveEvent(QMouseEvent *e)
{
    std::cerr << "move x: " << e->x()
              << " - y : " << e->y()
              << " - xDelta : " << e->x() - m_prevX
              << " - yDelta : " << e->y() - m_prevY
              << std::endl;

    m_prevX = e->x();
    m_prevY = e->y();

    doDragAutoScroll();
}


void MyScrollView::updateBottomWidgetGeometry()
{
    if (!m_bottomWidget) return;

    int bottomWidgetHeight = m_bottomWidget->sizeHint().height();

    std::cerr << "MyScrollView::updateBottomWidgetGeometry() : bottomWidgetHeight = "
              << bottomWidgetHeight << std::endl;

    setMargins(0, 0, 0, bottomWidgetHeight);
    QRect r = frameRect();
    int hScrollBarHeight = 0;
    if (horizontalScrollBar()->isVisible())
        hScrollBarHeight = horizontalScrollBar()->height();

    int vScrollBarWidth = 0;
    if (verticalScrollBar()->isVisible())
        vScrollBarWidth = verticalScrollBar()->width();

    m_bottomWidget->setGeometry(r.x(),
                                r.y() + r.height() - bottomWidgetHeight - hScrollBarHeight,
                                r.width() - vScrollBarWidth,
                                bottomWidgetHeight);
}

int main(int argc, char** argv)
{
    QApplication app(argc,argv);

    QMainWindow *mainWin = new QMainWindow;

    QCanvas *canvas = new QCanvas(5000,5000);

    MyScrollView* sv = new MyScrollView(canvas, mainWin);
    
    mainWin->setCentralWidget(sv);

    QVBox* vbox = new QVBox(mainWin, "noscrollvbox");
    vbox->setFrameShape(QFrame::Box);
    sv->setBottomFixedWidget(vbox);

    new QLabel("No Scroll1", vbox, "noscrollqlabel1");
    new QLabel("No Scroll2", vbox, "noscrollqlabel2");

    qApp->setMainWidget(mainWin);
    
    mainWin->show();

    QObject::connect( qApp, SIGNAL(lastWindowClosed()), qApp, SLOT(quit()) );

    return app.exec();
}

Reply via email to