Fixed DnD in KDE4.
[mp-5.x.git] / mpv_kde4.cpp
blobef75faf75c119f586a1d884fd87ce3549321bdd4
1 /*
3 Minimum Profit - Programmer Text Editor
5 KDE4 driver.
7 Copyright (C) 2008-2009 Angel Ortega <angel@triptico.com>
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 http://www.triptico.com
27 /* override auto-generated definition in config.h */
28 extern "C" int kde4_drv_detect(int * argc, char *** argv);
30 #include "config.h"
32 #include <stdio.h>
33 #include <wchar.h>
34 #include <unistd.h>
35 #include "mpdm.h"
36 #include "mpsl.h"
37 #include "mp.h"
39 #include <QtGui/QKeyEvent>
40 #include <QtGui/QPainter>
41 #include <QtGui/QMenu>
43 #include <QtGui/QLabel>
44 #include <QtGui/QComboBox>
45 #include <QtGui/QLineEdit>
46 #include <QtGui/QCheckBox>
47 #include <QtGui/QListWidget>
48 #include <QtGui/QScrollBar>
49 #include <QtGui/QClipboard>
51 #include <KApplication>
52 #include <KAboutData>
53 #include <KCmdLineArgs>
55 #include <KMainWindow>
56 #include <KMenuBar>
57 #include <KStatusBar>
58 #include <KMenu>
59 #include <KTabBar>
61 #include <KVBox>
62 #include <KHBox>
64 #include <KDialog>
65 #include <KMessageBox>
66 #include <KFileDialog>
67 #include <KUrl>
69 #include "mp.xpm"
71 /** data **/
73 class MPWindow : public KMainWindow
75 public:
76 MPWindow(QWidget *parent = 0);
77 bool queryExit(void);
78 bool event(QEvent *event);
81 class MPArea : public QWidget
83 Q_OBJECT
85 public:
86 MPArea(QWidget *parent = 0);
87 void inputMethodEvent(QInputMethodEvent *event);
88 void keyPressEvent(QKeyEvent *event);
89 void keyReleaseEvent(QKeyEvent *event);
90 void mousePressEvent(QMouseEvent *event);
91 void mouseReleaseEvent(QMouseEvent *event);
92 void mouseMoveEvent(QMouseEvent *event);
93 void wheelEvent(QWheelEvent *event);
94 void dragEnterEvent(QDragEnterEvent *event);
95 void dropEvent(QDropEvent *event);
96 bool event(QEvent *event);
98 protected:
99 void paintEvent(QPaintEvent *event);
101 public slots:
102 void from_scrollbar(int);
103 void from_filetabs(int);
104 void from_menu(QAction *);
107 /* global data */
108 KApplication *app;
109 MPWindow *window;
110 MPArea *area;
111 KMenuBar *menubar;
112 KStatusBar *statusbar;
113 QScrollBar *scrollbar;
114 KTabBar *file_tabs;
116 static int font_width = -1;
117 static int font_height = -1;
118 static int mouse_down = 0;
119 static int key_down = 0;
121 /** code **/
123 static mpdm_t qstring_to_str(QString s)
124 /* converts a QString to an MPDM string */
126 mpdm_t r = NULL;
128 if (s != NULL) {
129 int t = s.size();
130 wchar_t *wptr = (wchar_t *)malloc((t + 1) * sizeof(wchar_t));
132 r = MPDM_ENS(wptr, t);
134 s.toWCharArray(wptr);
135 wptr[t] = L'\0';
138 return r;
142 QString str_to_qstring(mpdm_t s)
143 /* converts an MPDM string to a QString */
145 wchar_t *wptr = mpdm_string(s);
146 return QString::fromWCharArray(wptr);
150 #define MAX_COLORS 1000
151 QPen inks[MAX_COLORS];
152 QBrush papers[MAX_COLORS];
153 bool underlines[MAX_COLORS];
154 int normal_attr = 0;
156 static void build_colors(void)
157 /* builds the colors */
159 mpdm_t colors;
160 mpdm_t l;
161 mpdm_t c;
162 int n, s;
164 /* gets the color definitions and attribute names */
165 colors = mpdm_hget_s(mp, L"colors");
166 l = mpdm_keys(colors);
167 s = mpdm_size(l);
169 /* loop the colors */
170 for (n = 0; n < s && (c = mpdm_aget(l, n)) != NULL; n++) {
171 int rgbi, rgbp;
172 mpdm_t d = mpdm_hget(colors, c);
173 mpdm_t v = mpdm_hget_s(d, L"gui");
175 /* store the 'normal' attribute */
176 if (wcscmp(mpdm_string(c), L"normal") == 0)
177 normal_attr = n;
179 /* store the attr */
180 mpdm_hset_s(d, L"attr", MPDM_I(n));
182 rgbi = mpdm_ival(mpdm_aget(v, 0));
183 rgbp = mpdm_ival(mpdm_aget(v, 1));
185 /* flags */
186 v = mpdm_hget_s(d, L"flags");
188 if (mpdm_seek_s(v, L"reverse", 1) != -1) {
189 int t = rgbi;
190 rgbi = rgbp;
191 rgbp = t;
194 underlines[n] = mpdm_seek_s(v, L"underline", 1) != -1 ? true : false;
196 inks[n] = QPen(QColor::fromRgbF(
197 (float) ((rgbi & 0x00ff0000) >> 16) / 256.0,
198 (float) ((rgbi & 0x0000ff00) >> 8) / 256.0,
199 (float) ((rgbi & 0x000000ff)) / 256.0,
200 1));
202 papers[n] = QBrush(QColor::fromRgbF(
203 (float) ((rgbp & 0x00ff0000) >> 16) / 256.0,
204 (float) ((rgbp & 0x0000ff00) >> 8) / 256.0,
205 (float) ((rgbp & 0x000000ff)) / 256.0,
206 1));
211 static QFont build_font(int rebuild)
212 /* (re)builds the font */
214 static QFont font;
216 if (rebuild) {
217 mpdm_t c;
218 char * font_face = (char *)"Mono";
219 int font_size = 12;
221 if ((c = mpdm_hget_s(mp, L"config")) != NULL) {
222 mpdm_t v;
224 if ((v = mpdm_hget_s(c, L"font_size")) != NULL)
225 font_size = mpdm_ival(v);
226 else
227 mpdm_hset_s(c, L"font_size", MPDM_I(font_size));
229 if ((v = mpdm_hget_s(c, L"font_face")) != NULL) {
230 v = MPDM_2MBS((wchar_t *)v->data);
231 font_face = (char *)v->data;
233 else
234 mpdm_hset_s(c, L"font_face", MPDM_MBS(font_face));
237 font = QFont(QString(font_face), font_size);
240 return font;
244 static void build_menu(void)
245 /* builds the menu */
247 int n;
248 mpdm_t m;
250 /* gets the current menu */
251 if ((m = mpdm_hget_s(mp, L"menu")) == NULL)
252 return;
254 menubar->clear();
256 for (n = 0; n < mpdm_size(m); n++) {
257 mpdm_t mi;
258 mpdm_t v;
259 int i;
261 /* get the label */
262 mi = mpdm_aget(m, n);
263 v = mpdm_aget(mi, 0);
265 KMenu *menu = new KMenu(str_to_qstring(mpdm_gettext(v)));
267 /* get the items */
268 v = mpdm_aget(mi, 1);
270 for (i = 0; i < mpdm_size(v); i++) {
271 wchar_t *wptr;
272 mpdm_t w = mpdm_aget(v, i);
274 wptr = mpdm_string(w);
276 if (*wptr == L'-')
277 menu->addSeparator();
278 else
279 menu->addAction(str_to_qstring(
280 mp_menu_label(w)));
283 menubar->addMenu(menu);
286 menubar->show();
290 static int ignore_scrollbar_signal = 0;
292 static void draw_scrollbar(void)
294 static int ol = -1;
295 static int ovy = -1;
296 static int oty = -1;
297 mpdm_t txt = mpdm_hget_s(mp_active(), L"txt");
298 mpdm_t window = mpdm_hget_s(mp, L"window");
299 int vy = mpdm_ival(mpdm_hget_s(txt, L"vy"));
300 int ty = mpdm_ival(mpdm_hget_s(window, L"ty"));
301 int l = mpdm_size(mpdm_hget_s(txt, L"lines")) - ty;
303 if (ol != l || ovy != vy || oty != ty) {
305 ignore_scrollbar_signal = 1;
307 scrollbar->setMinimum(0);
308 scrollbar->setMaximum(ol = l);
309 scrollbar->setValue(ovy = vy);
310 scrollbar->setPageStep(oty = ty);
312 ignore_scrollbar_signal = 0;
317 static void draw_status(void)
319 statusbar->changeItem(str_to_qstring(mp_build_status_line()), 0);
322 static void draw_filetabs(void)
324 static mpdm_t last = NULL;
325 mpdm_t names;
326 int n, i;
328 names = mp_get_doc_names();
330 /* get mp.active_i now, because it can be changed
331 from the signal handler */
332 i = mpdm_ival(mpdm_hget_s(mp, L"active_i"));
334 /* is the list different from the previous one? */
335 if (mpdm_cmp(names, last) != 0) {
337 while (file_tabs->count())
338 file_tabs->removeTab(0);
340 /* create the new ones */
341 for (n = 0; n < mpdm_size(names); n++)
342 file_tabs->addTab(str_to_qstring(mpdm_aget(names, n)));
344 /* store for the next time */
345 mpdm_unref(last);
346 last = mpdm_ref(names);
349 /* set the active one */
350 file_tabs->setCurrentIndex(i);
354 /** MPArea methods **/
356 MPArea::MPArea(QWidget *parent) : QWidget(parent)
358 setAttribute(Qt::WA_InputMethodEnabled, true);
360 setAcceptDrops(true);
364 bool MPArea::event(QEvent *event)
366 /* special tab processing */
367 if (event->type() == QEvent::KeyPress) {
368 QKeyEvent *ke = (QKeyEvent *)event;
370 if (ke->key() == Qt::Key_Tab) {
371 mp_process_event(MPDM_LS(L"tab"));
372 area->update();
373 return true;
377 /* keep normal processing */
378 return QWidget::event(event);
381 void MPArea::paintEvent(QPaintEvent *)
383 mpdm_t w;
384 int n, m, y;
385 QFont font;
386 bool underline = false;
388 QPainter painter(this);
390 font = build_font(0);
391 font.setUnderline(false);
392 painter.setFont(font);
394 font_width = painter.fontMetrics().width("M");
395 font_height = painter.fontMetrics().height();
397 /* calculate window size */
398 w = mpdm_hget_s(mp, L"window");
399 mpdm_hset_s(w, L"tx", MPDM_I(this->width() / font_width));
400 mpdm_hset_s(w, L"ty", MPDM_I(this->height() / font_height));
402 w = mp_draw(mp_active(), 0);
403 y = painter.fontMetrics().ascent() + 1;
405 painter.setBackgroundMode(Qt::OpaqueMode);
407 painter.setBrush(papers[normal_attr]);
408 painter.drawRect(0, 0, this->width(), this->height());
410 for (n = 0; n < mpdm_size(w); n++) {
411 mpdm_t l = mpdm_aget(w, n);
412 int x = 0;
414 if (l == NULL)
415 continue;
417 for (m = 0; m < mpdm_size(l); m++) {
418 int attr;
419 mpdm_t s;
421 /* get the attribute and the string */
422 attr = mpdm_ival(mpdm_aget(l, m++));
423 s = mpdm_aget(l, m);
425 painter.setPen(inks[attr]);
426 painter.setBackground(papers[attr]);
428 QString qs = str_to_qstring(s);
430 if (underline != underlines[attr]) {
431 underline = underlines[attr];
432 font.setUnderline(underline);
433 painter.setFont(font);
436 painter.drawText(x, y, qs);
438 x += painter.fontMetrics().width(qs);
441 y += font_height;
444 draw_filetabs();
445 draw_scrollbar();
446 draw_status();
448 area->setFocus(Qt::OtherFocusReason);
452 void MPArea::inputMethodEvent(QInputMethodEvent *event)
454 QString s = event->commitString();
456 mp_process_event(qstring_to_str(s));
457 area->update();
461 void MPArea::keyReleaseEvent(QKeyEvent *event)
463 if (!event->isAutoRepeat()) {
464 key_down = 0;
466 if (mp_keypress_throttle(0))
467 area->update();
472 void MPArea::keyPressEvent(QKeyEvent *event)
474 mpdm_t k = NULL;
475 wchar_t *ptr = NULL;
477 key_down = 1;
479 /* set mp.shift_pressed */
480 if (event->modifiers() & Qt::ShiftModifier)
481 mpdm_hset_s(mp, L"shift_pressed", MPDM_I(1));
483 if (event->modifiers() & Qt::ControlModifier) {
484 switch (event->key()) {
485 case Qt::Key_Up: ptr = (wchar_t *) L"ctrl-cursor-up"; break;
486 case Qt::Key_Down: ptr = (wchar_t *) L"ctrl-cursor-down"; break;
487 case Qt::Key_Left: ptr = (wchar_t *) L"ctrl-cursor-left"; break;
488 case Qt::Key_Right: ptr = (wchar_t *) L"ctrl-cursor-right"; break;
489 case Qt::Key_PageUp: ptr = (wchar_t *) L"ctrl-page-up"; break;
490 case Qt::Key_PageDown: ptr = (wchar_t *) L"ctrl-page-down"; break;
491 case Qt::Key_Home: ptr = (wchar_t *) L"ctrl-home"; break;
492 case Qt::Key_End: ptr = (wchar_t *) L"ctrl-end"; break;
493 case Qt::Key_Space: ptr = (wchar_t *) L"ctrl-space"; break;
494 case Qt::Key_F1: ptr = (wchar_t *) L"ctrl-f1"; break;
495 case Qt::Key_F2: ptr = (wchar_t *) L"ctrl-f2"; break;
496 case Qt::Key_F3: ptr = (wchar_t *) L"ctrl-f3"; break;
497 case Qt::Key_F4: ptr = (wchar_t *) L"ctrl-f4"; break;
498 case Qt::Key_F5: ptr = (wchar_t *) L"ctrl-f5"; break;
499 case Qt::Key_F6: ptr = (wchar_t *) L"ctrl-f6"; break;
500 case Qt::Key_F7: ptr = (wchar_t *) L"ctrl-f7"; break;
501 case Qt::Key_F8: ptr = (wchar_t *) L"ctrl-f8"; break;
502 case Qt::Key_F9: ptr = (wchar_t *) L"ctrl-f9"; break;
503 case Qt::Key_F10: ptr = (wchar_t *) L"ctrl-f10"; break;
504 case Qt::Key_F11: ptr = (wchar_t *) L"ctrl-f11"; break;
505 case Qt::Key_F12: ptr = (wchar_t *) L"ctrl-f12"; break;
506 case 'A': ptr = (wchar_t *) L"ctrl-a"; break;
507 case 'B': ptr = (wchar_t *) L"ctrl-b"; break;
508 case 'C': ptr = (wchar_t *) L"ctrl-c"; break;
509 case 'D': ptr = (wchar_t *) L"ctrl-d"; break;
510 case 'E': ptr = (wchar_t *) L"ctrl-e"; break;
511 case 'F': ptr = (wchar_t *) L"ctrl-f"; break;
512 case 'G': ptr = (wchar_t *) L"ctrl-g"; break;
513 case 'H': ptr = (wchar_t *) L"ctrl-h"; break;
514 case 'I': ptr = (wchar_t *) L"ctrl-i"; break;
515 case 'J': ptr = (wchar_t *) L"ctrl-j"; break;
516 case 'K': ptr = (wchar_t *) L"ctrl-k"; break;
517 case 'L': ptr = (wchar_t *) L"ctrl-l"; break;
518 case 'M': ptr = (wchar_t *) L"ctrl-m"; break;
519 case 'N': ptr = (wchar_t *) L"ctrl-n"; break;
520 case 'O': ptr = (wchar_t *) L"ctrl-o"; break;
521 case 'P': ptr = (wchar_t *) L"ctrl-p"; break;
522 case 'Q': ptr = (wchar_t *) L"ctrl-q"; break;
523 case 'R': ptr = (wchar_t *) L"ctrl-r"; break;
524 case 'S': ptr = (wchar_t *) L"ctrl-s"; break;
525 case 'T': ptr = (wchar_t *) L"ctrl-t"; break;
526 case 'U': ptr = (wchar_t *) L"ctrl-u"; break;
527 case 'V': ptr = (wchar_t *) L"ctrl-v"; break;
528 case 'W': ptr = (wchar_t *) L"ctrl-w"; break;
529 case 'X': ptr = (wchar_t *) L"ctrl-x"; break;
530 case 'Y': ptr = (wchar_t *) L"ctrl-y"; break;
531 case 'Z': ptr = (wchar_t *) L"ctrl-z"; break;
532 case Qt::Key_Return:
533 case Qt::Key_Enter: ptr = (wchar_t *) L"ctrl-enter"; break;
535 default:
536 break;
539 else {
540 switch (event->key()) {
541 case Qt::Key_Up: ptr = (wchar_t *) L"cursor-up"; break;
542 case Qt::Key_Down: ptr = (wchar_t *) L"cursor-down"; break;
543 case Qt::Key_Left: ptr = (wchar_t *) L"cursor-left"; break;
544 case Qt::Key_Right: ptr = (wchar_t *) L"cursor-right"; break;
545 case Qt::Key_PageUp: ptr = (wchar_t *) L"page-up"; break;
546 case Qt::Key_PageDown: ptr = (wchar_t *) L"page-down"; break;
547 case Qt::Key_Home: ptr = (wchar_t *) L"home"; break;
548 case Qt::Key_End: ptr = (wchar_t *) L"end"; break;
549 case Qt::Key_Space: ptr = (wchar_t *) L"space"; break;
550 case Qt::Key_F1: ptr = (wchar_t *) L"f1"; break;
551 case Qt::Key_F2: ptr = (wchar_t *) L"f2"; break;
552 case Qt::Key_F3: ptr = (wchar_t *) L"f3"; break;
553 case Qt::Key_F4: ptr = (wchar_t *) L"f4"; break;
554 case Qt::Key_F5: ptr = (wchar_t *) L"f5"; break;
555 case Qt::Key_F6: ptr = (wchar_t *) L"f6"; break;
556 case Qt::Key_F7: ptr = (wchar_t *) L"f7"; break;
557 case Qt::Key_F8: ptr = (wchar_t *) L"f8"; break;
558 case Qt::Key_F9: ptr = (wchar_t *) L"f9"; break;
559 case Qt::Key_F10: ptr = (wchar_t *) L"f10"; break;
560 case Qt::Key_F11: ptr = (wchar_t *) L"f11"; break;
561 case Qt::Key_F12: ptr = (wchar_t *) L"f12"; break;
562 case Qt::Key_Insert: ptr = (wchar_t *) L"insert"; break;
563 case Qt::Key_Backspace: ptr = (wchar_t *) L"backspace"; break;
564 case Qt::Key_Delete: ptr = (wchar_t *) L"delete"; break;
565 case Qt::Key_Return:
566 case Qt::Key_Enter: ptr = (wchar_t *) L"enter"; break;
567 case Qt::Key_Escape: ptr = (wchar_t *) L"escape"; break;
569 default:
570 break;
574 if (ptr == NULL)
575 k = qstring_to_str(event->text());
576 else
577 k = MPDM_S(ptr);
579 if (k != NULL)
580 mp_process_event(k);
582 if (mp_keypress_throttle(1))
583 area->update();
587 void MPArea::mousePressEvent(QMouseEvent *event)
589 wchar_t *ptr = NULL;
591 mouse_down = 1;
593 QPoint pos = event->pos();
595 mpdm_hset_s(mp, L"mouse_x", MPDM_I(pos.x() / font_width));
596 mpdm_hset_s(mp, L"mouse_y", MPDM_I(pos.y() / font_height));
598 switch (event->button()) {
599 case Qt::LeftButton: ptr = (wchar_t *)L"mouse-left-button"; break;
600 case Qt::MidButton: ptr = (wchar_t *)L"mouse-middle-button"; break;
601 case Qt::RightButton: ptr = (wchar_t *)L"mouse-right-button"; break;
602 default:
603 break;
606 if (ptr != NULL)
607 mp_process_event(MPDM_S(ptr));
609 area->update();
613 void MPArea::mouseReleaseEvent(QMouseEvent *event)
615 mouse_down = 0;
619 void MPArea::mouseMoveEvent(QMouseEvent *event)
621 static int ox = 0;
622 static int oy = 0;
624 if (mouse_down) {
625 int x, y;
627 QPoint pos = event->pos();
629 /* mouse dragging */
630 x = pos.x() / font_width;
631 y = pos.y() / font_height;
633 if (ox != x && oy != y) {
634 mpdm_hset_s(mp, L"mouse_to_x", MPDM_I(x));
635 mpdm_hset_s(mp, L"mouse_to_y", MPDM_I(y));
637 mp_process_event(MPDM_LS(L"mouse-drag"));
639 area->update();
645 void MPArea::wheelEvent(QWheelEvent *event)
647 if (event->delta() > 0)
648 mp_process_event(MPDM_S(L"mouse-wheel-up"));
649 else
650 mp_process_event(MPDM_S(L"mouse-wheel-down"));
652 area->update();
656 void MPArea::dragEnterEvent(QDragEnterEvent *event)
658 if (event->mimeData()->hasFormat("text/uri-list"))
659 event->acceptProposedAction();
663 void MPArea::dropEvent(QDropEvent *event)
665 int n;
666 mpdm_t v = qstring_to_str(event->mimeData()->text());
667 mpdm_t l = MPDM_A(0);
669 /* split the list of files */
670 v = mpdm_split(MPDM_LS(L"\n"), v);
672 for (n = 0; n < mpdm_size(v); n++) {
673 wchar_t *ptr;
674 mpdm_t w = mpdm_aget(v, n);
676 /* strip file:///, if found */
677 ptr = mpdm_string(w);
679 if (wcsncmp(ptr, L"file://", 7) == 0)
680 ptr += 7;
682 if (*ptr != L'\0')
683 mpdm_push(l, MPDM_S(ptr));
686 mpdm_hset_s(mp, L"dropped_files", l);
688 event->acceptProposedAction();
689 mp_process_event(MPDM_LS(L"dropped-files"));
691 area->update();
695 /** MPArea slots **/
697 void MPArea::from_scrollbar(int value)
699 if (!ignore_scrollbar_signal) {
700 mpdm_t v = mp_active();
702 mp_set_y(v, value);
704 /* set the vy to the same value */
705 v = mpdm_hget_s(v, L"txt");
706 mpdm_hset_s(v, L"vy", MPDM_I(value));
708 area->update();
713 void MPArea::from_filetabs(int value)
715 if (value >= 0) {
716 /* sets the active one */
717 mpdm_hset_s(mp, L"active_i", MPDM_I(value));
718 area->update();
723 void MPArea::from_menu(QAction *action)
725 mpdm_t label = qstring_to_str(action->text());
726 label = mpdm_sregex(MPDM_LS(L"/&/"), label, NULL, 0);
728 mpdm_t a = mpdm_hget_s(mp, L"actions_by_menu_label");
730 mp_process_action(mpdm_hget(a, label));
731 area->update();
735 /** MPWindow methods **/
737 MPWindow::MPWindow(QWidget *parent) : KMainWindow(parent)
739 menubar = this->menuBar();
740 build_menu();
742 statusbar = this->statusBar();
743 statusbar->insertItem("mp " VERSION, 0);
745 /* the full container */
746 KVBox *vb = new KVBox(this);
748 file_tabs = new KTabBar(vb);
749 file_tabs->setFocusPolicy(Qt::NoFocus);
751 KHBox *hb = new KHBox(vb);
753 /* main area */
754 area = new MPArea(hb);
755 scrollbar = new QScrollBar(hb);
756 scrollbar->setFocusPolicy(Qt::NoFocus);
758 setCentralWidget(vb);
760 connect(scrollbar, SIGNAL(valueChanged(int)),
761 area, SLOT(from_scrollbar(int)));
763 connect(file_tabs, SIGNAL(currentChanged(int)),
764 area, SLOT(from_filetabs(int)));
766 connect(menubar, SIGNAL(triggered(QAction *)),
767 area, SLOT(from_menu(QAction *)));
769 this->setWindowIcon(QIcon(QPixmap(mp_xpm)));
771 this->setAutoSaveSettings(QLatin1String("MinimumProfit"), true);
775 bool MPWindow::queryExit(void)
777 mp_process_event(MPDM_LS(L"close-window"));
779 this->saveAutoSaveSettings();
781 return mp_exit_requested ? true : false;
785 bool MPWindow::event(QEvent *event)
787 /* do the processing */
788 bool r = QWidget::event(event);
790 if (mp_exit_requested) {
791 this->saveAutoSaveSettings();
792 exit(0);
795 return r;
799 /** driver functions **/
801 static mpdm_t kde4_drv_update_ui(mpdm_t a)
803 build_font(1);
804 build_colors();
805 build_menu();
807 return NULL;
811 static mpdm_t kde4_drv_alert(mpdm_t a)
812 /* alert driver function */
814 /* 1# arg: prompt */
815 KMessageBox::information(0, str_to_qstring(mpdm_aget(a, 0)),
816 i18n("mp " VERSION));
818 return NULL;
821 static mpdm_t kde4_drv_confirm(mpdm_t a)
822 /* confirm driver function */
824 int r;
826 /* 1# arg: prompt */
827 r = KMessageBox::questionYesNoCancel(0,
828 str_to_qstring(mpdm_aget(a, 0)), i18n("mp" VERSION));
830 switch (r) {
831 case KMessageBox::Yes:
832 r = 1;
833 break;
835 case KMessageBox::No:
836 r = 2;
837 break;
839 case KMessageBox::Cancel:
840 r = 0;
841 break;
844 return MPDM_I(r);
848 static mpdm_t kde4_drv_openfile(mpdm_t a)
850 QString r;
851 char tmp[128];
853 getcwd(tmp, sizeof(tmp));
855 /* 1# arg: prompt */
856 r = KFileDialog::getOpenFileName(KUrl::fromPath(tmp), "*", 0,
857 str_to_qstring(mpdm_aget(a, 0)));
859 return qstring_to_str(r);
863 static mpdm_t kde4_drv_savefile(mpdm_t a)
865 QString r;
866 char tmp[128];
868 getcwd(tmp, sizeof(tmp));
870 /* 1# arg: prompt */
871 r = KFileDialog::getSaveFileName(KUrl::fromPath(tmp), "*", 0,
872 str_to_qstring(mpdm_aget(a, 0)));
874 return qstring_to_str(r);
878 static mpdm_t kde4_drv_form(mpdm_t a)
880 int n;
881 mpdm_t widget_list;
882 QWidget *qlist[100];
883 mpdm_t r;
885 KDialog *dialog = new KDialog(window);
887 dialog->setModal(true);
888 dialog->setButtons(KDialog::Ok | KDialog::Cancel);
890 widget_list = mpdm_aget(a, 0);
892 KVBox *vb = new KVBox(dialog);
893 dialog->setMainWidget(vb);
895 for (n = 0; n < mpdm_size(widget_list); n++) {
896 mpdm_t w = mpdm_aget(widget_list, n);
897 wchar_t *type;
898 mpdm_t t;
899 KHBox *hb = new KHBox(vb);
901 type = mpdm_string(mpdm_hget_s(w, L"type"));
903 if ((t = mpdm_hget_s(w, L"label")) != NULL) {
904 QLabel *ql = new QLabel(hb);
905 ql->setText(str_to_qstring(mpdm_gettext(t)));
908 t = mpdm_hget_s(w, L"value");
910 if (wcscmp(type, L"text") == 0) {
911 mpdm_t h;
912 QComboBox *ql = new QComboBox(hb);
914 ql->setEditable(true);
915 ql->setMinimumContentsLength(30);
916 ql->setMaxVisibleItems(8);
918 if (t != NULL)
919 ql->setEditText(str_to_qstring(t));
921 qlist[n] = ql;
923 if ((h = mpdm_hget_s(w, L"history")) != NULL) {
924 int i;
926 /* has history; fill it */
927 h = mp_get_history(h);
929 for (i = mpdm_size(h) - 1; i >= 0; i--)
930 ql->addItem(str_to_qstring(mpdm_aget(h, i)));
933 else
934 if (wcscmp(type, L"password") == 0) {
935 QLineEdit *ql = new QLineEdit(hb);
937 ql->setEchoMode(QLineEdit::Password);
939 qlist[n] = ql;
941 else
942 if (wcscmp(type, L"checkbox") == 0) {
943 QCheckBox *qc = new QCheckBox(hb);
945 if (mpdm_ival(t))
946 qc->setCheckState(Qt::Checked);
948 qlist[n] = qc;
950 else
951 if (wcscmp(type, L"list") == 0) {
952 int i;
953 QListWidget *ql = new QListWidget(hb);
954 ql->setMinimumWidth(480);
956 /* use a monospaced font */
957 ql->setFont(QFont(QString("Mono")));
959 mpdm_t l = mpdm_hget_s(w, L"list");
961 for (i = 0; i < mpdm_size(l); i++)
962 ql->addItem(str_to_qstring(mpdm_aget(l, i)));
964 ql->setCurrentRow(mpdm_ival(t));
966 qlist[n] = ql;
969 if (n == 0)
970 qlist[n]->setFocus(Qt::OtherFocusReason);
973 n = dialog->exec();
975 if (!n)
976 return NULL;
978 r = MPDM_A(mpdm_size(widget_list));
980 /* fill the return values */
981 for (n = 0; n < mpdm_size(widget_list); n++) {
982 mpdm_t w = mpdm_aget(widget_list, n);
983 mpdm_t v = NULL;
984 wchar_t *type;
986 type = mpdm_string(mpdm_hget_s(w, L"type"));
988 if (wcscmp(type, L"text") == 0) {
989 mpdm_t h;
990 QComboBox *ql = (QComboBox *)qlist[n];
992 v = qstring_to_str(ql->currentText());
994 /* if it has history, add to it */
995 if ((h = mpdm_hget_s(w, L"history")) != NULL &&
996 v != NULL && mpdm_cmp(v, MPDM_LS(L"")) != 0) {
997 h = mp_get_history(h);
999 if (mpdm_cmp(v, mpdm_aget(h, -1)) != 0)
1000 mpdm_push(h, v);
1003 else
1004 if (wcscmp(type, L"password") == 0) {
1005 QLineEdit *ql = (QLineEdit *)qlist[n];
1007 v = qstring_to_str(ql->text());
1009 else
1010 if (wcscmp(type, L"checkbox") == 0) {
1011 QCheckBox *qb = (QCheckBox *)qlist[n];
1013 v = MPDM_I(qb->checkState() == Qt::Checked);
1015 else
1016 if (wcscmp(type, L"list") == 0) {
1017 QListWidget *ql = (QListWidget *)qlist[n];
1019 v = MPDM_I(ql->currentRow());
1022 mpdm_aset(r, v, n);
1025 return r;
1029 static mpdm_t kde4_drv_busy(mpdm_t a)
1031 int onoff = mpdm_ival(mpdm_aget(a, 0));
1033 window->setCursor(onoff ? Qt::WaitCursor : Qt::ArrowCursor);
1035 return NULL;
1039 static mpdm_t kde4_drv_main_loop(mpdm_t a)
1041 app->exec();
1043 return NULL;
1047 static mpdm_t kde4_drv_shutdown(mpdm_t a)
1049 mpdm_t v;
1051 if ((v = mpdm_hget_s(mp, L"exit_message")) != NULL) {
1052 mpdm_write_wcs(stdout, mpdm_string(v));
1053 printf("\n");
1056 return NULL;
1060 static mpdm_t kde4_drv_clip_to_sys(mpdm_t a)
1062 mpdm_t v;
1064 QClipboard *qc = QApplication::clipboard();
1066 /* gets the clipboard and joins */
1067 v = mpdm_hget_s(mp, L"clipboard");
1069 if (mpdm_size(v) != 0) {
1070 v = mpdm_join(MPDM_LS(L"\n"), v);
1071 qc->setText(str_to_qstring(v), QClipboard::Selection);
1074 return NULL;
1078 static mpdm_t kde4_drv_sys_to_clip(mpdm_t a)
1080 QClipboard *qc = QApplication::clipboard();
1081 QString qs = qc->text(QClipboard::Selection);
1083 /* split and set as the clipboard */
1084 mpdm_hset_s(mp, L"clipboard", mpdm_split(MPDM_LS(L"\n"),
1085 qstring_to_str(qs)));
1086 mpdm_hset_s(mp, L"clipboard_vertical", MPDM_I(0));
1088 return NULL;
1092 static void register_functions(void)
1094 mpdm_t drv;
1096 drv = mpdm_hget_s(mp, L"drv");
1097 mpdm_hset_s(drv, L"main_loop", MPDM_X(kde4_drv_main_loop));
1098 mpdm_hset_s(drv, L"shutdown", MPDM_X(kde4_drv_shutdown));
1100 mpdm_hset_s(drv, L"clip_to_sys", MPDM_X(kde4_drv_clip_to_sys));
1101 mpdm_hset_s(drv, L"sys_to_clip", MPDM_X(kde4_drv_sys_to_clip));
1102 mpdm_hset_s(drv, L"update_ui", MPDM_X(kde4_drv_update_ui));
1103 /* mpdm_hset_s(drv, L"timer", MPDM_X(kde4_drv_timer));*/
1104 mpdm_hset_s(drv, L"busy", MPDM_X(kde4_drv_busy));
1106 mpdm_hset_s(drv, L"alert", MPDM_X(kde4_drv_alert));
1107 mpdm_hset_s(drv, L"confirm", MPDM_X(kde4_drv_confirm));
1108 mpdm_hset_s(drv, L"openfile", MPDM_X(kde4_drv_openfile));
1109 mpdm_hset_s(drv, L"savefile", MPDM_X(kde4_drv_savefile));
1110 mpdm_hset_s(drv, L"form", MPDM_X(kde4_drv_form));
1114 static mpdm_t kde4_drv_startup(mpdm_t a)
1115 /* driver initialization */
1117 register_functions();
1119 build_font(1);
1120 build_colors();
1122 window = new MPWindow();
1123 window->show();
1125 return NULL;
1128 extern "C" Display *XOpenDisplay(char *);
1130 extern "C" int kde4_drv_detect(int * argc, char *** argv)
1132 mpdm_t drv;
1133 KCmdLineOptions opts;
1134 Display *x11_display;
1136 /* try connecting directly to the Xserver */
1137 if ((x11_display = XOpenDisplay((char *)NULL)) == NULL)
1138 return 0;
1140 KAboutData aboutData(
1141 "mp", 0,
1142 ki18n("Minimum Profit"), VERSION,
1143 ki18n("A programmer's text editor"),
1144 KAboutData::License_GPL,
1145 ki18n("Copyright (c) 1991-2009 Angel Ortega"),
1146 ki18n(""),
1147 "http://triptico.com",
1148 "angel@triptico.com"
1151 KCmdLineArgs::init(*argc, *argv, &aboutData);
1153 /* command line options should be inserted here (I don't like this) */
1154 opts.add("t {tag}", ki18n("Edits the file where tag is defined"));
1155 opts.add("e {mpsl_code}", ki18n("Executes MPSL code"));
1156 opts.add("f {mpsl_script}", ki18n("Executes MPSL script file"));
1157 opts.add("d {directory}", ki18n("Sets working directory"));
1158 opts.add("x {file}", ki18n("Open file in the hexadecimal viewer"));
1159 opts.add(" +NNN", ki18n("Moves to line number NNN of last file"));
1160 opts.add("+[file(s)]", ki18n("Documents to open"));
1161 KCmdLineArgs::addCmdLineOptions(opts);
1163 /* this is where it crashes if no X server */
1164 app = new KApplication(x11_display);
1166 drv = mpdm_hget_s(mp, L"drv");
1167 mpdm_hset_s(drv, L"id", MPDM_LS(L"kde4"));
1168 mpdm_hset_s(drv, L"startup", MPDM_X(kde4_drv_startup));
1170 return 1;
1173 #include "mpv_kde4.moc"