Colin’s Blog

A C++ Programmer

Texmacs/Mogan Note 2

23_15

1(get-init-tree "text-at-halign")

这个与缓存有关。缓存位置在~/.Texmacs/。如果不更改缓存,更改源代码不会生效。

23_7

 1(tm-define (graphics-release-left x y)
 2  ;;(display* "Graphics] Release-left " x ", " y "\n")
 3  (if (inside-graphical-text?)
 4      (with-innermost t graphical-text-context?
 5        (let* ((ps (select-first (s2f x) (s2f y)))
 6               (p (and ps (car ps))))
 7          (if (and p (list-starts? p (tree->path t)))
 8              (go-to p)
 9              (tree-go-to t :start))))
10      (edit_left-button (car (graphics-mode)) x y)))
1(tm-define (get-keyboard-modifiers)
2  the-keyboard-modifiers)
3
4(tm-define (set-keyboard-modifiers mods)
5  (set! the-keyboard-modifiers mods))

结论:https://github.com/XmacsLabs/mogan/pull/796

问题

  1. .ts文件怎么使用
  2. C++代码中有很多字符串类型的东西可以用枚举类型来替代,可以重构一下?
  3. 绘图模式有没有给座标系标注1、2、3的模式

编译时候出现问题

1generating scheme glueA glue_font ... ok
2generating scheme glueA glue_analyze ... ok
3generating scheme glueA glue_drd ... ok
4installing libmogan ..
5error: install failed, method 'trim' is not callable (a nil value)

看起来是lua语言中的trim方法无法调用。 结论:有一个环境变量字符串被设置为nil,之后在他的上面调用trim方法则报错。

23_14

edit_interface_rep::handle_mouse 处理鼠标事件。

1edit_interface_rep::handle_mouse (string kind, SI x, SI y, int m, time_t t,
2                                  array<double> data)

kind的类型可以有move, press-left, release-left, press-right 等。

 1else {
 2    string rew= kind;
 3    SI dist= (SI) (5 * PIXEL / magf);
 4    rew= detect_left_drag ((void*) this, rew, x, y, t, m, dist);
 5    if (rew == "start-drag-left") {
 6      call_mouse_event (rew, left_x, left_y, m, t, data);
 7      delayed_call_mouse_event ("dragging-left", x, y, m, t, data);
 8    }
 9    else {
10      rew= detect_right_drag ((void*) this, rew, x, y, t, m, dist);
11      if (rew == "start-drag-right") {
12        call_mouse_event (rew, right_x, right_y, m, t, data);
13        delayed_call_mouse_event ("dragging-right", x, y, m, t, data);
14      }
15      else call_mouse_event (rew, x, y, m, t, data);
16    }
17  }

这段检测了是否有拖动发生,如果没有,最终会执行call_mouse_event (rew, x, y, m, t, data);

1static void
2call_mouse_event (string kind, SI x, SI y, SI m, time_t t, array<double> d) {
3  array<object> args;
4  args << object (kind) << object (x) << object (y)
5       << object (m) << object ((double) t) << object (d);
6  call ("mouse-event", args);
7}

然后转发给scheme来处理。

1(tm-define (mouse-event key x y mods time data)
2  ;;(display* "mouse-event " key ", " x ", " y ", " mods ", " time ", " data "\n")
3  (mouse-any key x y mods (+ time 0.0) data))

转到mouse-any

mouse-any再转回C++

 1{
 2                scm_name = "mouse-any",
 3                cpp_name = "mouse_any",
 4                ret_type = "void",
 5                arg_list = {
 6                    "string",
 7                    "int",
 8                    "int",
 9                    "int",
10                    "double",
11                    "array_double"
12                }
13            },

mouse_any中进行dispatch.

1  if (type == "press-left" || type == "start-drag-left") {
2    if (mods > 1) {
3      mouse_adjusting = mods;
4      mouse_adjust_selection(x, y, mods);
5    } else
6      mouse_click (x, y);
7  }

在这里进入mouse_click函数

1void
2edit_interface_rep::mouse_click (SI x, SI y) {
3  if (mouse_message ("click", x, y)) return;
4  start_x= x;
5  start_y= y;
6  send_mouse_grab (this, true);
7}

思路改为倒着找,从绘图的移动功能出发。因为只需要在绘图上进行改变鼠标样式的操作,而改变鼠标样式(setCursor)是依赖于具体的widget来执行的。

1(tm-define (edit_move mode x y)
1(tm-define (graphics-move x y)
2  ;;(display* "Graphics] Move " x ", " y "\n")
3  (when (not (inside-graphical-text?))
4    (edit_move (car (graphics-mode)) x y)))

根据("Move objects" (graphics-set-mode '(group-edit move))), 应该重载到group-edit版本。

测试发现正确:

 1(tm-define (edit_move mode x y)
 2  (:require (eq? mode 'group-edit))
 3  (:state graphics-state)
 4  (display* "HERE\n")
 5  (cond (sticky-point
 6         (set! x (s2f x))
 7         (set! y (s2f y))
 8         (with mode (graphics-mode)
 9           (cond ((== (cadr mode) 'move)
10                  (sketch-transform
11                   (group-translate (- x group-old-x)
12                                    (- y group-old-y))))
13                 ((== (cadr mode) 'zoom)
14                  (sketch-set! group-first-go)
15                  (sketch-transform (group-zoom x y)))
16                 ((== (cadr mode) 'rotate)
17                  (sketch-set! group-first-go)
18                  (sketch-transform (group-rotate x y)))))
19         (set! group-old-x x)
20         (set! group-old-y y))
21        (multiselecting
22         (graphical-object!
23          (append
24           (create-graphical-props 'default #f)
25           `((with color red
26               (cline (point ,selecting-x0 ,selecting-y0)
27                      (point ,x ,selecting-y0)
28                      (point ,x ,y)
29                      (point ,selecting-x0 ,y)))))))
30        (else
31          (cond (current-path
32                 (set-message (string-append "Left click: operate; "
33                                             "Shift+Left click or Right click: select/unselect")
34                              "Group of objects"))
35                ((nnull? (sketch-get))
36                 (set-message "Left click: operate"
37                              "Group of objects"))
38                (else
39                  (set-message "Move over object on which to operate"
40                               "Edit groups of objects")))
41          (graphics-decorations-update))))

之后倒到edit_graphics.cpp中的:

1bool
2edit_graphics_rep::mouse_graphics (string type, SI x, SI y, int mods, time_t t,
3                                   array<double> data) {

倒退到

1bool
2edit_graphics_rep::mouse_graphics (string type, SI x, SI y, int mods, time_t t,
3                                   array<double> data) {

然后倒退到scheme中。没找到可以利用的。

换思路,搜索: public QWidget,看都有谁继承了。因为setCursor是它的成员函数。QtMainWindow也是Qt库中的,它也继承了QWidget.

看不出。直接看主界面怎么生成的吧。

qt_tm_widget.hpp中写了:

1  QMainWindow* mainwindow () {
2    return qobject_cast<QMainWindow*> (qwid); 
3  }

这个函数可以获取主页面的QWidget. 但它仍然是一个成员函数所以可能不太对。

qt_dialogues.cpp中,发现了

1 QWidget* mainwindow = QApplication::activeWindow ();

这个可能是Qt自带的找到当前活跃窗口的函数。

23_14 Bug

 1(tm-define (graphics-get-property var)
 2  (with val (graphics-get-raw-property var)
 3    (tm->stree val)))
 4
 5(define (graphics-get-raw-property var)
 6  (with val (get-upwards-tree-property (graphics-graphics-path) var)
 7    (if (eq? val nothing)
 8        (get-default-tree-val var)
 9        (if (eq? (tm-car val) 'quote)
10            (tree-ref val 0)
11            val))))

研究 get-env-tree

1tree
2edit_typeset_rep::get_env_value (string var, path p) {
3  typeset_exec_until (p);
4  tree t= cur[p][var];
5  return is_func (t, BACKUP, 2)? t[0]: t;
6}

鼠标点击研究

1  if (type == "press-left" || type == "start-drag-left") {
2    if (mods > 1) {
3      mouse_adjusting = mods;
4      mouse_adjust_selection(x, y, mods);
5    } else
6      mouse_click (x, y);
7  }

之后进入

1void
2edit_interface_rep::mouse_click (SI x, SI y) {
3  cout << "DEBUG: ";
4  if (mouse_message ("click", x, y)) return;
5  start_x= x;
6  start_y= y;
7  send_mouse_grab (this, true);
8}

之后

1inline void
2send_mouse_grab (widget w, bool get_grab) {
3  // request a mouse grab for the widget
4  send<bool> (w, SLOT_MOUSE_GRAB, get_grab);
5}

在这里似乎捕获了

 1void
 2qt_tm_widget_rep::send (slot s, blackbox val) {
 3  switch (s) {
 4    case SLOT_INVALIDATE:
 5    case SLOT_INVALIDATE_ALL:
 6    case SLOT_EXTENTS:
 7    case SLOT_SCROLL_POSITION:
 8    case SLOT_ZOOM_FACTOR:
 9    case SLOT_MOUSE_GRAB:
10      main_widget->send(s, val);
11      return;

似乎会跑到这里

1    case SLOT_MOUSE_GRAB:
2    {
3      check_type<bool> (val, s);
4      bool grab = open_box<bool>(val);
5      if (grab && canvas() && !canvas()->hasFocus())
6        canvas()->setFocus (Qt::MouseFocusReason);
7    }
8      break;