00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexiscrollview.h"
00021
00022 #include <qcursor.h>
00023 #include <qobjectlist.h>
00024 #include <qpainter.h>
00025 #include <qpixmap.h>
00026
00027 #include <kdebug.h>
00028 #include <kstaticdeleter.h>
00029 #include <klocale.h>
00030
00031 #include <utils/kexirecordnavigator.h>
00032 #include <core/kexi.h>
00033 #include <kexiutils/utils.h>
00034
00036 class KexiScrollViewData
00037 {
00038 public:
00039 QPixmap horizontalOuterAreaPixmapBuffer;
00040 QPixmap verticalOuterAreaPixmapBuffer;
00041 };
00042
00043
00044 static KStaticDeleter<KexiScrollViewData> KexiScrollView_data_deleter;
00045 KexiScrollViewData* KexiScrollView_data = 0;
00046
00047 KexiScrollView::KexiScrollView(QWidget *parent, bool preview)
00048 : QScrollView(parent, "kexiscrollview", WStaticContents)
00049 , m_widget(0)
00050 , m_helpFont(font())
00051 , m_preview(preview)
00052 , m_scrollViewNavPanel(0)
00053 {
00054 setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
00055 viewport()->setPaletteBackgroundColor(colorGroup().mid());
00056 QColor fc = palette().active().foreground(),
00057 bc = viewport()->paletteBackgroundColor();
00058 m_helpColor = KexiUtils::blendedColors(fc, bc, 1, 2);
00059
00060
00061 m_helpFont.setPointSize( m_helpFont.pointSize() * 3 );
00062
00063 setFocusPolicy(WheelFocus);
00064
00065
00066
00067 setResizePolicy(Manual);
00068
00069 viewport()->setMouseTracking(true);
00070 m_resizing = false;
00071 m_enableResizing = true;
00072 m_snapToGrid = false;
00073 m_gridSize = 0;
00074 m_outerAreaVisible = true;
00075
00076 connect(&m_delayedResize, SIGNAL(timeout()), this, SLOT(refreshContentsSize()));
00077 m_smodeSet = false;
00078 if (m_preview) {
00079 refreshContentsSizeLater(true, true);
00081 updateScrollBars();
00082 m_scrollViewNavPanel = new KexiRecordNavigator(this, leftMargin(), "nav");
00083 m_scrollViewNavPanel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred);
00084 }
00085 }
00086
00087 KexiScrollView::~KexiScrollView()
00088 {
00089 }
00090
00091 void
00092 KexiScrollView::setWidget(QWidget *w)
00093 {
00094 addChild(w);
00095 m_widget = w;
00096 }
00097
00098 void
00099 KexiScrollView::setRecordNavigatorVisible(bool visible)
00100 {
00101 if( !visible)
00102 m_scrollViewNavPanel->hide();
00103 else if(visible) {
00104 m_scrollViewNavPanel->show();
00105 updateNavPanelGeometry();
00106 }
00107 }
00108
00109 void
00110 KexiScrollView::setSnapToGrid(bool enable, int gridSize)
00111 {
00112 m_snapToGrid = enable;
00113 if(enable) {
00114 m_gridSize = gridSize;
00115 }
00116 }
00117
00118 void
00119 KexiScrollView::refreshContentsSizeLater(bool horizontal, bool vertical)
00120 {
00121 Q_UNUSED( horizontal );
00122 Q_UNUSED( vertical );
00123
00124 if (!m_smodeSet) {
00125 m_smodeSet = true;
00126 m_vsmode = vScrollBarMode();
00127 m_hsmode = hScrollBarMode();
00128 }
00129
00130 setVScrollBarMode(QScrollView::AlwaysOff);
00131
00132 setHScrollBarMode(QScrollView::AlwaysOff);
00133 updateScrollBars();
00134 m_delayedResize.start( 100, true );
00135 }
00136
00137 void
00138 KexiScrollView::refreshContentsSize()
00139 {
00140 if(!m_widget)
00141 return;
00142 if (m_preview) {
00143 resizeContents(m_widget->width(), m_widget->height());
00144
00145
00146 setVScrollBarMode(m_vsmode);
00147 setHScrollBarMode(m_hsmode);
00148 m_smodeSet = false;
00149 updateScrollBars();
00150 }
00151 else {
00152
00153 int w = contentsWidth(), h = contentsHeight();
00154 bool change = false;
00155 const int delta_x = QMAX( (KexiScrollView_data ?
00156 KexiScrollView_data->verticalOuterAreaPixmapBuffer.width() : 0), 300);
00157 const int delta_y = QMAX( (KexiScrollView_data ?
00158 KexiScrollView_data->horizontalOuterAreaPixmapBuffer.height() : 0), 300);
00159 if((m_widget->width() + delta_x * 2 / 3) > w) {
00160 w = m_widget->width() + delta_x;
00161 change = true;
00162 }
00163 else if((w - m_widget->width()) > delta_x) {
00164 w = m_widget->width() + delta_x;
00165 change = true;
00166 }
00167 if((m_widget->height() + delta_y * 2 / 3) > h) {
00168 h = m_widget->height() + delta_y;
00169 change = true;
00170 }
00171 else if((h - m_widget->height()) > delta_y) {
00172 h = m_widget->height() + delta_y;
00173 change = true;
00174 }
00175 if (change) {
00176 repaint();
00177 viewport()->repaint();
00178 repaintContents();
00179 updateContents(0, 0, 2000,2000);
00180 clipper()->repaint();
00181
00182 resizeContents(w, h);
00183 }
00184
00185
00186 updateScrollBars();
00187 setVScrollBarMode(Auto);
00188 setHScrollBarMode(Auto);
00189 }
00190 updateContents();
00191 updateScrollBars();
00192 }
00193
00194 void
00195 KexiScrollView::updateNavPanelGeometry()
00196 {
00197 if (m_scrollViewNavPanel)
00198 m_scrollViewNavPanel->updateGeometry(leftMargin());
00199 }
00200
00201 void
00202 KexiScrollView::contentsMousePressEvent(QMouseEvent *ev)
00203 {
00204 if(!m_widget)
00205 return;
00206
00207 QRect r3(0, 0, m_widget->width() + 4, m_widget->height() + 4);
00208 if(!r3.contains(ev->pos()))
00209
00210 emit outerAreaClicked();
00211
00212 if(!m_enableResizing)
00213 return;
00214
00215 QRect r(m_widget->width(), 0, 4, m_widget->height() + 4);
00216 QRect r2(0, m_widget->height(), m_widget->width() + 4, 4);
00217 if(r.contains(ev->pos()) || r2.contains(ev->pos()))
00218 {
00219 m_resizing = true;
00220 emit resizingStarted();
00221 }
00222 }
00223
00224 void
00225 KexiScrollView::contentsMouseReleaseEvent(QMouseEvent *)
00226 {
00227 if(m_resizing) {
00228 m_resizing = false;
00229 emit resizingEnded();
00230 }
00231
00232 unsetCursor();
00233 }
00234
00235 void
00236 KexiScrollView::contentsMouseMoveEvent(QMouseEvent *ev)
00237 {
00238 if(!m_widget || !m_enableResizing)
00239 return;
00240
00241 if(m_resizing)
00242 {
00243 int tmpx = ev->x(), tmpy = ev->y();
00244 const int exceeds_x = (tmpx - contentsX() + 5) - clipper()->width();
00245 const int exceeds_y = (tmpy - contentsY() + 5) - clipper()->height();
00246 if (exceeds_x > 0)
00247 tmpx -= exceeds_x;
00248 if (exceeds_y > 0)
00249 tmpy -= exceeds_y;
00250 if ((tmpx - contentsX()) < 0)
00251 tmpx = contentsX();
00252 if ((tmpy - contentsY()) < 0)
00253 tmpy = contentsY();
00254
00255
00256 QObjectList *list = m_widget->queryList("QWidget", 0, true, false );
00257 for(QObject *o = list->first(); o; o = list->next())
00258 {
00259 QWidget *w = (QWidget*)o;
00260 tmpx = QMAX(tmpx, (w->geometry().right() + 10));
00261 tmpy = QMAX(tmpy, (w->geometry().bottom() + 10));
00262 }
00263 delete list;
00264
00265 int neww = -1, newh;
00266 if(cursor().shape() == QCursor::SizeHorCursor)
00267 {
00268 if(m_snapToGrid)
00269 neww = int( float(tmpx) / float(m_gridSize) + 0.5 ) * m_gridSize;
00270 else
00271 neww = tmpx;
00272 newh = m_widget->height();
00273 }
00274 else if(cursor().shape() == QCursor::SizeVerCursor)
00275 {
00276 neww = m_widget->width();
00277 if(m_snapToGrid)
00278 newh = int( float(tmpy) / float(m_gridSize) + 0.5 ) * m_gridSize;
00279 else
00280 newh = tmpy;
00281 }
00282 else if(cursor().shape() == QCursor::SizeFDiagCursor)
00283 {
00284 if(m_snapToGrid) {
00285 neww = int( float(tmpx) / float(m_gridSize) + 0.5 ) * m_gridSize;
00286 newh = int( float(tmpy) / float(m_gridSize) + 0.5 ) * m_gridSize;
00287 } else {
00288 neww = tmpx;
00289 newh = tmpy;
00290 }
00291 }
00292
00293 if (neww!=-1 && m_widget->size() != QSize(neww, newh)) {
00294 m_widget->resize( neww, newh );
00295 refreshContentsSize();
00296 updateContents();
00297 }
00298 }
00299 else
00300 {
00301 QPoint p = ev->pos();
00302 QRect r(m_widget->width(), 0, 4, m_widget->height());
00303 QRect r2(0, m_widget->height(), m_widget->width(), 4);
00304 QRect r3(m_widget->width(), m_widget->height(), 4, 4);
00305
00306 if(r.contains(p))
00307 setCursor(QCursor::SizeHorCursor);
00308 else if(r2.contains(p))
00309 setCursor(QCursor::SizeVerCursor);
00310 else if(r3.contains(p))
00311 setCursor(QCursor::SizeFDiagCursor);
00312 else
00313 unsetCursor();
00314 }
00315 }
00316
00317 void
00318 KexiScrollView::setupPixmapBuffer(QPixmap& pixmap, const QString& text, int lines)
00319 {
00320 Q_UNUSED( lines );
00321
00322 QFontMetrics fm(m_helpFont);
00323 const int flags = Qt::AlignCenter|Qt::AlignTop;
00324 QRect rect(fm.boundingRect(0,0,1000,1000,flags,text));
00325 const int txtw = rect.width(), txth = rect.height();
00326 pixmap = QPixmap(txtw, txth);
00327 if (!pixmap.isNull()) {
00328
00329 pixmap.fill( viewport()->paletteBackgroundColor() );
00330 QPainter pb(&pixmap, this);
00331 pb.setPen(m_helpColor);
00332 pb.setFont(m_helpFont);
00333 pb.drawText(0, 0, txtw, txth, Qt::AlignCenter|Qt::AlignTop, text);
00334 }
00335 }
00336
00337 void
00338 KexiScrollView::drawContents( QPainter * p, int clipx, int clipy, int clipw, int cliph )
00339 {
00340 QScrollView::drawContents(p, clipx, clipy, clipw, cliph);
00341 if (m_widget) {
00342 if(m_preview || !m_outerAreaVisible)
00343 return;
00344
00345
00346 const int wx = childX(m_widget);
00347 const int wy = childY(m_widget);
00348 p->setPen(palette().active().foreground());
00349 p->drawLine(wx+m_widget->width(), wy, wx+m_widget->width(), wy+m_widget->height());
00350 p->drawLine(wx, wy+m_widget->height(), wx+m_widget->width(), wy+m_widget->height());
00351
00352
00353 if (!KexiScrollView_data) {
00354 KexiScrollView_data_deleter.setObject( KexiScrollView_data, new KexiScrollViewData() );
00355
00356
00357 setupPixmapBuffer( KexiScrollView_data->horizontalOuterAreaPixmapBuffer, i18n("Outer Area"), 1 );
00358 setupPixmapBuffer( KexiScrollView_data->verticalOuterAreaPixmapBuffer, i18n("Outer\nArea"), 2 );
00359 }
00360 if (!KexiScrollView_data->horizontalOuterAreaPixmapBuffer.isNull()
00361 && !KexiScrollView_data->verticalOuterAreaPixmapBuffer.isNull()
00362 && !m_delayedResize.isActive() )
00363 {
00364 if (m_widget->height()>(KexiScrollView_data->verticalOuterAreaPixmapBuffer.height()+20)) {
00365 p->drawPixmap(
00366 QMAX( m_widget->width(), KexiScrollView_data->verticalOuterAreaPixmapBuffer.width() + 20 ) + 20,
00367 QMAX( (m_widget->height() - KexiScrollView_data->verticalOuterAreaPixmapBuffer.height())/2, 20 ),
00368 KexiScrollView_data->verticalOuterAreaPixmapBuffer
00369 );
00370 }
00371 p->drawPixmap(
00372 QMAX( (m_widget->width() - KexiScrollView_data->horizontalOuterAreaPixmapBuffer.width())/2, 20 ),
00373 QMAX( m_widget->height(), KexiScrollView_data->horizontalOuterAreaPixmapBuffer.height() + 20 ) + 20,
00374 KexiScrollView_data->horizontalOuterAreaPixmapBuffer
00375 );
00376 }
00377 }
00378 }
00379
00380 void
00381 KexiScrollView::leaveEvent( QEvent *e )
00382 {
00383 QWidget::leaveEvent(e);
00384 m_widget->update();
00385 }
00386
00387 void
00388 KexiScrollView::setHBarGeometry( QScrollBar & hbar, int x, int y, int w, int h )
00389 {
00390
00391
00392 if (m_scrollViewNavPanel && m_scrollViewNavPanel->isVisible()) {
00393 m_scrollViewNavPanel->setHBarGeometry( hbar, x, y, w, h );
00394 }
00395 else {
00396 hbar.setGeometry( x, y, w, h );
00397 }
00398 }
00399
00400 KexiRecordNavigator*
00401 KexiScrollView::recordNavigator() const
00402 {
00403 return m_scrollViewNavPanel;
00404 }
00405
00406 #include "kexiscrollview.moc"
00407