~ubuntu-branches/ubuntu/quantal/texmacs/quantal

« back to all changes in this revision

Viewing changes to src/Plugins/Qt/QTMWidget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Atsuhito KOHDA
  • Date: 2010-04-23 07:09:40 UTC
  • mfrom: (1.2.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20100423070940-juy8n05xs1b6au8i
Re-upload, former upload failed with wrong diff.gz perhaps.

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
#include "QTMWidget.hpp"
15
15
#include "qt_renderer.hpp"
16
16
#include "qt_gui.hpp"
 
17
#include "qt_utilities.hpp"
17
18
#include "qt_simple_widget.hpp"
18
 
 
19
19
#include "converter.hpp"
20
20
 
21
21
#include "config.h"
 
22
#include "message.hpp" 
22
23
 
23
24
#ifdef USE_CAIRO
24
25
#include "Cairo/cairo_renderer.hpp"
37
38
 
38
39
#define PIXEL 256
39
40
 
40
 
extern bool qt_update_flag;
41
 
extern time_t time_credit;
42
 
extern time_t timeout_time;
 
41
QSet<QTMWidget*> QTMWidget::all_widgets;
 
42
 
43
43
 
44
44
hashmap<int,string> qtkeymap (0);
45
45
hashmap<int,string> qtdeadmap (0);
149
149
  // map (Qt::Key_ModeSwitchFunctionKey, "modeswitch" );
150
150
}
151
151
 
152
 
void
153
 
QTMWidget::postponedUpdate () {
154
 
#ifdef Q_WS_MAC
155
 
  //FIXME: the call below to update is ignored sometimes (usually in long documents).
156
 
  //       It is a confirmed Qt/Mac bug (#251792). See
157
 
  //       http://www.qtsoftware.com/developer/task-tracker/index_html?method=entry&id=251792
158
 
  //FIXME: This is a workaround for the update(rect) bug. Mac specific.
159
 
  if (DEBUG_QT) {
160
 
    cout << "postponedUpdate (ALL)\n";
161
 
  }
162
 
  update();
163
 
  delayed_rects= list<QRect>();
164
 
#else
165
 
  while (!is_nil (delayed_rects)) {
166
 
    QRect rect = delayed_rects->item;
167
 
    if (DEBUG_QT) {
168
 
      cout << "postponedUpdate (" << rect.x()
169
 
      << "," <<  rect.y()
170
 
      << "," <<  rect.width()
171
 
      << "," <<  rect.height() << ")\n" ;
172
 
    }
173
 
    update (rect);
174
 
    delayed_rects= delayed_rects->next;
175
 
  }
176
 
#endif
177
 
}
178
 
 
179
 
 
180
 
void QTMWidget::resizeEvent( QResizeEvent* event )
181
 
{
182
 
  //cout << "QTMWidget::resizeEvent (" << event->size().width() << "," << event->size().height() << ")" << LF;
183
 
  QWidget::resizeEvent (event);
184
 
#if defined(Q_WS_X11) && defined(USE_CAIRO)
185
 
  backingPixmap = QPixmap(width(),height());
186
 
#endif
187
 
}
188
 
 
189
 
void
190
 
QTMWidget::paintEvent (QPaintEvent* event) {
191
 
  //cout << "paint"<< LF;
192
 
  QRect rect = event->rect ();
193
 
  bool partial_redraw = false;
194
 
 
195
 
  if (DEBUG_QT) {
196
 
    QPainter p(this);
197
 
    QBrush brush (QColor ("red"));
198
 
    p.fillRect (rect, brush);
199
 
    p.end ();
200
 
 
201
 
    cout << "paintEvent ("<< rect.x()
202
 
    << "," <<  rect.y()
203
 
    << "," <<  rect.width()
204
 
    << "," <<  rect.height() << ")\n" ;
205
 
 
206
 
  }
207
 
 
208
 
  if (!qt_update_flag) {
209
 
    //time_t start= texmacs_time ();
210
 
    basic_renderer_rep *r;
211
 
 
 
152
 
 
153
 
 
154
QTMWidget::QTMWidget (simple_widget_rep *_wid) 
 
155
  : QTMScrollView (), backingPixmap() {
 
156
  setObjectName("A QTMWidget");
 
157
  setProperty ("texmacs_widget", QVariant::fromValue ((void*) _wid));
 
158
  QAbstractScrollArea::viewport()->setMouseTracking (true);
 
159
  QAbstractScrollArea::viewport()->setFocusPolicy (Qt::StrongFocus);
 
160
  backing_pos = origin;
 
161
}
 
162
 
 
163
 
 
164
QTMWidget::~QTMWidget () {
 
165
  if (DEBUG_QT) cout << "destroying " << this << LF;
 
166
}
 
167
 
 
168
void 
 
169
QTMWidget::invalidate_rect (int x1, int y1, int x2, int y2) {
 
170
  rectangle r = rectangle (x1, y1, x2, y2);
 
171
  // cout << "invalidating " << r << LF;
 
172
  invalid_regions = invalid_regions | rectangles (r);
 
173
}
 
174
 
 
175
void 
 
176
QTMWidget::invalidate_all () {
 
177
  QSize sz = QAbstractScrollArea::viewport()->size();
 
178
   //cout << "invalidate all " << LF;
 
179
  invalid_regions = rectangles();
 
180
  invalidate_rect (0, 0, sz.width(), sz.height());
 
181
}
 
182
 
 
183
 
 
184
basic_renderer_rep* 
 
185
QTMWidget::getRenderer() {
212
186
#ifdef USE_CAIRO
213
 
    r = the_cairo_renderer ();
214
 
    cairo_surface_t *surf;
 
187
  cairo_renderer_rep *ren = the_cairo_renderer ();
 
188
  cairo_surface_t *surf;
215
189
#ifdef Q_WS_X11
216
 
    //const QX11Info & info = x11Info();//qt_x11Info(this);
217
 
    //    Display *dpy = x11Info().display();
218
 
    //backingPixmap = QPixmap(width(),height());
219
 
    //cout << backingPixmap.width() << LF;
220
 
    Display *dpy = QX11Info::display();
221
 
    Drawable drawable = backingPixmap.handle();
222
 
    Visual *visual = (Visual*)(backingPixmap.x11Info().visual());
223
 
    surf = tm_cairo_xlib_surface_create (dpy, drawable, visual, backingPixmap.width (), backingPixmap.height ());
 
190
  //const QX11Info & info = x11Info();//qt_x11Info(this);
 
191
  //    Display *dpy = x11Info().display();
 
192
  //backingPixmap = QPixmap(width(),height());
 
193
  //cout << backingPixmap.width() << LF;
 
194
  Display *dpy = QX11Info::display();
 
195
  Drawable drawable = backingPixmap.handle();
 
196
  Visual *visual = (Visual*)(backingPixmap.x11Info().visual());
 
197
  surf = tm_cairo_xlib_surface_create (dpy, drawable, visual, 
 
198
                            backingPixmap.width (), backingPixmap.height ());
224
199
#elif defined(Q_WS_MAC)
225
 
    surf = tm_cairo_quartz_surface_create_for_cg_context ((CGContextRef)(this->macCGHandle()), width(), height());
 
200
  surf = tm_cairo_quartz_surface_create_for_cg_context (
 
201
                    (CGContextRef)(this->macCGHandle()), width(), height());
226
202
#endif
227
 
    cairo_t *ct = tm_cairo_create (surf);
228
 
    r->begin (ct);
229
 
    tm_cairo_surface_destroy (surf);
230
 
    tm_cairo_destroy (ct);
 
203
  cairo_t *ct = tm_cairo_create (surf);
 
204
  ren->begin (ct);
 
205
  tm_cairo_surface_destroy (surf);
 
206
  tm_cairo_destroy (ct);
231
207
#else
232
 
    r = the_qt_renderer();
233
 
    r->begin (static_cast<QPaintDevice*>(this));
234
 
#endif
235
 
 
236
 
    tm_widget()->set_current_renderer(r);
237
 
 
238
 
 
239
 
 
240
 
    r -> set_clipping
241
 
    (rect.x()*PIXEL, -(rect.y()+rect.height())*PIXEL,
242
 
     (rect.x()+rect.width())*PIXEL, -rect.y()*PIXEL);
243
 
    tm_widget()->handle_repaint
244
 
    (rect.x()*PIXEL, -(rect.y()+rect.height())*PIXEL,
245
 
     (rect.x()+rect.width())*PIXEL, -rect.y()*PIXEL);
246
 
 
247
 
    if (r->interrupted()) {
248
 
      if (DEBUG_QT)
249
 
        cout << "Interrupted\n";
250
 
      qt_update_flag= true;
251
 
      partial_redraw = true;
252
 
    }
253
 
 
254
 
    r->end();
255
 
 
256
 
    tm_widget()->set_current_renderer(NULL);
257
 
    //time_t end= texmacs_time ();
258
 
    //if (end > start) cout << "Repaint " << end - start << "\n";
259
 
  }
260
 
 
261
 
 
262
 
#if defined(Q_WS_X11) && defined(USE_CAIRO)
263
 
  {
264
 
    // copy pixmap to screen
265
 
    QPainter painter (this);
266
 
    painter.drawPixmap (0,0,backingPixmap);
267
 
  }
268
 
#endif
269
 
 
270
 
 
271
 
  if (partial_redraw) 
272
 
  {
273
 
    if (DEBUG_QT)
274
 
      cout << "Postponed redrawing\n";
275
 
    delayed_rects= list<QRect> (rect, delayed_rects);
276
 
    QTimer::singleShot (1, this, SLOT (postponedUpdate ()));
277
 
  }
 
208
  qt_renderer_rep * ren = the_qt_renderer();
 
209
  ren->begin(&backingPixmap);
 
210
#endif
 
211
  return ren;
 
212
}
 
213
 
 
214
void
 
215
QTMWidget::repaint_invalid_regions () {
 
216
 
 
217
  // this function is called by the qt_gui::update method to keep the backing
 
218
  // store in sync and propagate the changes to the surface on screen.
 
219
  // first we check that the backing store geometry is right and then we
 
220
  // request to the texmacs canvas widget to repaint the regions which were
 
221
  // marked invalid. Subsequently, for each succesfully repainted region, we
 
222
  // propagate its contents from the backing store to the onscreen surface.
 
223
  // If repaint has been interrupted we do not propagate the changes and proceed
 
224
  // to mark the region invalid again.
 
225
 
 
226
  QRegion qrgn; 
 
227
  // qrgn is to keep track of the area on the sceen which needs to be updated 
 
228
 
 
229
  // update backing store origin wrt. TeXmacs document
 
230
  if ( backing_pos != origin ) {
 
231
 
 
232
    int dx =  origin.x() - backing_pos.x();
 
233
    int dy =  origin.y() - backing_pos.y();
 
234
    backing_pos = origin;
 
235
    
 
236
    QPixmap newBackingPixmap (backingPixmap.size());
 
237
    QPainter p (&newBackingPixmap);
 
238
    //newBackingPixmap.fill(Qt::black);
 
239
    p.drawPixmap(-dx,-dy,backingPixmap);
 
240
    p.end();
 
241
    backingPixmap = newBackingPixmap;
 
242
    //cout << "SCROLL CONTENTS BY " << dx << " " << dy << LF;
 
243
    
 
244
    QSize sz = backingPixmap.size();
 
245
    
 
246
    rectangles invalid;
 
247
    while (!is_nil(invalid_regions)) {
 
248
      rectangle r = invalid_regions->item ;
 
249
      //      rectangle q = rectangle(r->x1+dx,r->y1-dy,r->x2+dx,r->y2-dy);
 
250
      rectangle q = rectangle(r->x1-dx,r->y1-dy,r->x2-dx,r->y2-dy);
 
251
      invalid = rectangles (q, invalid);
 
252
      //cout << r << " ---> " << q << LF;
 
253
      invalid_regions = invalid_regions->next;
 
254
    }
 
255
    invalid_regions= invalid & 
 
256
    rectangles(rectangle(0,0,
 
257
                         sz.width(),sz.height())) ;
 
258
    
 
259
    if (dy<0) 
 
260
      invalidate_rect(0,0,sz.width(),min(sz.height(),-dy));
 
261
    else if (dy>0)
 
262
      invalidate_rect(0,max(0,sz.height()-dy),sz.width(),sz.height());
 
263
    
 
264
    if (dx<0) 
 
265
      invalidate_rect(0,0,min(-dx,sz.width()),sz.height());
 
266
    else if (dx>0)
 
267
      invalidate_rect(max(0,sz.width()-dx),0,sz.width(),sz.height());
 
268
    
 
269
    // we cal update now to allow repainint of invalid regions
 
270
    // this cannot be done directly since interpose handler needs
 
271
    // to be run at least once in some situations
 
272
    // (for example when scrolling is initiated by TeXmacs itself)
 
273
    //the_gui->update();
 
274
    //  QAbstractScrollArea::viewport()->scroll(-dx,-dy);
 
275
   // QAbstractScrollArea::viewport()->update();
 
276
    qrgn += QRect(QPoint(0,0),sz);
 
277
  }
 
278
  
 
279
  // update backing store size
 
280
  {
 
281
    QSize _oldSize = backingPixmap.size();
 
282
    QSize _newSize = QAbstractScrollArea::viewport()->size();
 
283
    if (_newSize != _oldSize) {
 
284
      // cout << "RESIZING BITMAP"<< LF;
 
285
      QPixmap newBackingPixmap (_newSize);
 
286
      //QPainter p (&newBackingPixmap);
 
287
      //p.drawPixmap(0,0,backingPixmap);
 
288
      //p.end();
 
289
      backingPixmap = newBackingPixmap;
 
290
      invalidate_all();
 
291
      the_gui -> process_resize(tm_widget(), 0, 0); // FIXME
 
292
    }
 
293
  }
 
294
  
 
295
  // repaint invalid rectangles
 
296
  {
 
297
    rectangles new_regions;
 
298
    if (!is_nil (invalid_regions)) {
 
299
      rectangle lub= least_upper_bound (invalid_regions);
 
300
      if (area (lub) < 1.2 * area (invalid_regions))
 
301
        invalid_regions= rectangles (lub);
 
302
      
 
303
      basic_renderer_rep* ren = getRenderer();
 
304
      tm_widget()->set_current_renderer(ren);
 
305
      
 
306
      SI ox = -backing_pos.x()*PIXEL;
 
307
      SI oy = backing_pos.y()*PIXEL;
 
308
      
 
309
      rectangles rects = invalid_regions;
 
310
      invalid_regions = rectangles();
 
311
      
 
312
      while (!is_nil (rects)) {
 
313
        rectangle r = copy (rects->item);
 
314
        rectangle r0 = rects->item;
 
315
        QRect qr = QRect(r0->x1, r0->y1, r0->x2 - r0->x1, r0->y2 - r0->y1);
 
316
        //cout << "repainting " << r0 << "\n";
 
317
        ren->set_origin(ox,oy); 
 
318
        ren->encode (r->x1, r->y1);
 
319
        ren->encode (r->x2, r->y2);
 
320
        ren->set_clipping (r->x1, r->y2, r->x2, r->y1);
 
321
        tm_widget()->handle_repaint (r->x1, r->y2, r->x2, r->y1);
 
322
        if (ren->interrupted ()) {
 
323
          //cout << "interrupted repainting of  " << r0 << "\n";
 
324
          //ren->set_color(green);
 
325
          //ren->line(r->x1, r->y1, r->x2, r->y2);
 
326
          //ren->line(r->x1, r->y2, r->x2, r->y1);
 
327
          invalidate_rect (r0->x1, r0->y1, r0->x2, r0->y2);
 
328
        } 
 
329
        qrgn += qr;
 
330
        rects = rects->next;
 
331
      }
 
332
      
 
333
      tm_widget()->set_current_renderer(NULL);
 
334
      ren->end();
 
335
    } // !is_nil(invalid_regions)
 
336
    
 
337
  }
 
338
 
 
339
  // propagate immediatly the changes to the screen  
 
340
  QAbstractScrollArea::viewport()->repaint(qrgn);
 
341
  
 
342
}
 
343
 
 
344
void 
 
345
QTMWidget::scrollContentsBy ( int dx, int dy ) {
 
346
  QTMScrollView::scrollContentsBy (dx,dy);
 
347
  // the_gui::update needs to be run as soon as possible to refresh the status
 
348
  // of the widget.
 
349
  needs_update(); 
 
350
}
 
351
 
 
352
void 
 
353
QTMWidget::resizeEvent( QResizeEvent* event ) {
 
354
  // cout << "QTMWidget::resizeEvent (" << event->size().width()
 
355
  //      << "," << event->size().height() << ")" << LF;
 
356
  QTMScrollView::resizeEvent (event);
 
357
  // the_gui::update needs to be run as soon as possible to refresh the status
 
358
  // of the widget.
 
359
  needs_update(); 
 
360
}
 
361
 
 
362
void
 
363
QTMWidget::paintEvent (QPaintEvent* event) {
 
364
  // In the current implementation repainting take place during the call to
 
365
  // the widget's repaint_invalid_regions method in the_gui::update. All
 
366
  // we have to do is to take the backing store and put it on screen according
 
367
  // to the QRegion marked invalid. 
 
368
  // CHECK: Maybe just put onscreen all the region bounding rectangle could not 
 
369
  // be so expensive.
 
370
  
 
371
  
 
372
  if (DEBUG_QT) 
 
373
  {
 
374
    QRect rect = event->rect ();
 
375
    cout << "paintEvent ("<< rect.x() << "," <<  rect.y()
 
376
    << "," <<  rect.width() << "," <<  rect.height() << ")" << LF ;
 
377
  }
 
378
    
 
379
  {    
 
380
    QPainter p (QAbstractScrollArea::viewport());
 
381
    QVector<QRect> rects = event->region().rects();
 
382
    for (int i=0; i< rects.count(); i++) {
 
383
      QRect qr = rects.at(i);
 
384
      p.drawPixmap(qr,backingPixmap,qr);
 
385
    }
 
386
  }
 
387
  
278
388
}
279
389
 
280
390
 
281
391
void
282
392
QTMWidget::keyPressEvent (QKeyEvent* event) {
283
 
  time_credit= 25;
284
 
  timeout_time= texmacs_time () + time_credit;
285
393
  static bool fInit = false;
286
394
  if (!fInit) {
287
395
    if (DEBUG_QT)
328
436
        r= string ((char) key);
329
437
      } else {
330
438
        switch(unic) {
331
 
        case 96:   r= "`"; // unicode to cork conversion not appropriate for this case...
 
439
        case 96:   r= "`"; 
 
440
            // unicode to cork conversion not appropriate for this case...
332
441
#ifdef Q_WS_MAC
333
442
          // CHECKME: are these two MAC exceptions really needed?
334
443
                   if (mods & Qt::AltModifier) r= "grave";
376
485
    if (DEBUG_QT)
377
486
      cout << "key press: " << r << LF;
378
487
    //int start= texmacs_time ();
379
 
    wid -> handle_keypress (r, texmacs_time());
 
488
    //wid -> handle_keypress (r, texmacs_time());
 
489
    the_gui -> process_keypress (wid, r, texmacs_time());
380
490
    //int end= texmacs_time ();
381
491
    //if (end > start) cout << "Keypress " << end - start << "\n";
382
 
    the_gui->update (); // FIXME: remove this line when
 
492
  //  the_gui->update (); // FIXME: remove this line when
383
493
                        // edit_typeset_rep::get_env_value will be faster
 
494
    
 
495
//    needs_update();
384
496
  }
385
497
}
386
498
 
424
536
QTMWidget::mousePressEvent (QMouseEvent* event) {
425
537
  simple_widget_rep *wid= tm_widget ();
426
538
  if (!wid) return;
427
 
  QPoint point = event->pos();
 
539
  QPoint point = event->pos() + origin;
428
540
  scale (point);
429
541
  unsigned int mstate= mouse_state (event, false);
430
542
  string s= "press-" * mouse_decode (mstate);
431
 
  wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
 
543
  the_gui -> process_mouse (wid, s, point.x (), point.y (), 
 
544
                            mstate, texmacs_time ());
 
545
 // wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
432
546
  if (DEBUG_QT)
433
547
    cout << "mouse event: " << s << " at "
434
548
         << point.x () << ", " << point.y () << LF;
438
552
QTMWidget::mouseReleaseEvent (QMouseEvent* event) {
439
553
  simple_widget_rep *wid = tm_widget();
440
554
  if (!wid) return;
441
 
  QPoint point = event->pos();
 
555
  QPoint point = event->pos() + origin;;
442
556
  scale (point);
443
557
  unsigned int mstate= mouse_state (event, true);
444
558
  string s= "release-" * mouse_decode (mstate);
445
 
  wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
 
559
  the_gui -> process_mouse (wid, s, point.x (), point.y (), 
 
560
                            mstate, texmacs_time ());
 
561
//  wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
446
562
  if (DEBUG_QT)
447
563
    cout << "mouse event: " << s << " at "
448
564
         << point.x () << ", " << point.y () << LF;
452
568
QTMWidget::mouseMoveEvent (QMouseEvent* event) {
453
569
  simple_widget_rep *wid = tm_widget();
454
570
  if (!wid) return;
455
 
  QPoint point = event->pos();
 
571
  QPoint point = event->pos() + origin;
456
572
  scale (point);
457
573
  unsigned int mstate= mouse_state (event, false);
458
574
  string s= "move";
459
 
  wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
 
575
  the_gui -> process_mouse (wid, s, point.x (), point.y (), 
 
576
                            mstate, texmacs_time ());
 
577
//  wid -> handle_mouse (s, point.x (), point.y (), mstate, texmacs_time ());
460
578
  if (DEBUG_QT)
461
579
    cout << "mouse event: " << s << " at "
462
580
         << point.x () << ", " << point.y () << LF;
470
588
    keyPressEvent (ke);
471
589
    return true;
472
590
  }
473
 
  return QWidget::event (event);
 
591
  return QTMScrollView::event (event);
474
592
}
475
593
 
476
594
 
477
595
void
478
 
QTMWidget::focusInEvent ( QFocusEvent * event )
479
 
{
 
596
QTMWidget::focusInEvent ( QFocusEvent * event ) {
480
597
  if (DEBUG_QT) cout << "FOCUSIN" << LF;
481
598
  simple_widget_rep *wid = tm_widget ();
482
599
  if (wid) {
483
 
    wid -> handle_keyboard_focus (true, texmacs_time ());
 
600
    the_gui -> process_keyboard_focus (wid, true, texmacs_time());
 
601
    //wid -> handle_keyboard_focus (true, texmacs_time ());
484
602
  }
485
 
  QWidget::focusInEvent (event);
 
603
  QTMScrollView::focusInEvent (event);
486
604
}
487
605
 
488
606
void
489
 
QTMWidget::focusOutEvent ( QFocusEvent * event )
490
 
{
 
607
QTMWidget::focusOutEvent ( QFocusEvent * event ) {
491
608
  if (DEBUG_QT)   cout << "FOCUSOUT" << LF;
492
609
  simple_widget_rep *wid = tm_widget ();
493
610
  if (wid) {
494
 
    wid -> handle_keyboard_focus (false, texmacs_time ());
 
611
    the_gui -> process_keyboard_focus (wid, false, texmacs_time());
 
612
//    wid -> handle_keyboard_focus (false, texmacs_time ());
495
613
  }
496
 
  QWidget::focusOutEvent (event);
 
614
  QTMScrollView::focusOutEvent (event);
497
615
}