Fix crash in new on_close handler.
[mp-5.x.git] / mpv_kde4.cpp
blob6b8520763796849c55d871c9580847950535e4bf
1 /*
3 Minimum Profit - Programmer Text Editor
5 KDE4 driver.
7 Copyright (C) 2008-2010 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"
38 #include "mp.xpm"
40 #include <QtGui/QKeyEvent>
41 #include <QtGui/QPainter>
42 #include <QtGui/QMenu>
44 #include <QtGui/QLabel>
45 #include <QtGui/QComboBox>
46 #include <QtGui/QLineEdit>
47 #include <QtGui/QCheckBox>
48 #include <QtGui/QListWidget>
49 #include <QtGui/QScrollBar>
50 #include <QtGui/QClipboard>
52 #include <KApplication>
53 #include <KAboutData>
54 #include <KCmdLineArgs>
56 #include <KMainWindow>
57 #include <KMenuBar>
58 #include <KStatusBar>
59 #include <KMenu>
60 #include <KTabBar>
62 #include <KVBox>
63 #include <KHBox>
65 #include <KDialog>
66 #include <KMessageBox>
67 #include <KFileDialog>
68 #include <KUrl>
70 /** data **/
72 class MPWindow : public KMainWindow
74 public:
75 MPWindow(QWidget * parent = 0);
76 bool queryExit(void);
77 bool event(QEvent * event);
80 class MPArea : public QWidget
82 Q_OBJECT
84 public:
85 MPArea(QWidget * parent = 0);
86 void inputMethodEvent(QInputMethodEvent * event);
87 void keyPressEvent(QKeyEvent * event);
88 void keyReleaseEvent(QKeyEvent * event);
89 void mousePressEvent(QMouseEvent * event);
90 void mouseReleaseEvent(QMouseEvent * event);
91 void mouseMoveEvent(QMouseEvent * event);
92 void wheelEvent(QWheelEvent * event);
93 void dragEnterEvent(QDragEnterEvent * event);
94 void dropEvent(QDropEvent * event);
95 bool event(QEvent * event);
97 QTimer *timer;
99 protected:
100 void paintEvent(QPaintEvent * event);
102 public slots: void from_scrollbar(int);
103 void from_filetabs(int);
104 void from_menu(QAction *);
105 void from_timer(void);
108 /* global data */
109 KApplication *app;
110 MPWindow *window;
111 KMenuBar *menubar;
112 KStatusBar *statusbar;
113 KTabBar *file_tabs;
115 #define MENU_CLASS KMenu
117 #include "mpv_qk_common.cpp"
119 static void draw_status(void)
121 statusbar->changeItem(str_to_qstring(mp_build_status_line()), 0);
124 /** MPWindow methods **/
126 MPWindow::MPWindow(QWidget * parent) : KMainWindow(parent)
128 menubar = this->menuBar();
129 build_menu();
131 statusbar = this->statusBar();
132 statusbar->insertItem("mp " VERSION, 0);
134 /* the full container */
135 KVBox *vb = new KVBox(this);
137 file_tabs = new KTabBar(vb);
138 file_tabs->setFocusPolicy(Qt::NoFocus);
140 KHBox *hb = new KHBox(vb);
142 /* main area */
143 area = new MPArea(hb);
144 scrollbar = new QScrollBar(hb);
145 scrollbar->setFocusPolicy(Qt::NoFocus);
147 setCentralWidget(vb);
149 connect(scrollbar, SIGNAL(valueChanged(int)),
150 area, SLOT(from_scrollbar(int)));
152 connect(file_tabs, SIGNAL(currentChanged(int)),
153 area, SLOT(from_filetabs(int)));
155 connect(menubar, SIGNAL(triggered(QAction *)),
156 area, SLOT(from_menu(QAction *)));
158 this->setWindowIcon(QIcon(QPixmap(mp_xpm)));
160 this->setAutoSaveSettings(QLatin1String("MinimumProfit"), true);
164 bool MPWindow::queryExit(void)
166 mp_process_event(MPDM_LS(L"close-window"));
168 this->saveAutoSaveSettings();
170 return mp_exit_requested ? true : false;
174 bool MPWindow::event(QEvent * event)
176 /* do the processing */
177 bool r = QWidget::event(event);
179 if (mp_exit_requested) {
180 this->saveAutoSaveSettings();
181 exit(0);
184 return r;
188 /** driver functions **/
190 static mpdm_t kde4_drv_update_ui(mpdm_t a, mpdm_t ctxt)
192 return qt4_drv_update_ui(a);
196 static mpdm_t kde4_drv_alert(mpdm_t a, mpdm_t ctxt)
197 /* alert driver function */
199 /* 1# arg: prompt */
200 KMessageBox::information(0, str_to_qstring(mpdm_aget(a, 0)),
201 i18n("mp " VERSION));
203 return NULL;
206 static mpdm_t kde4_drv_confirm(mpdm_t a, mpdm_t ctxt)
207 /* confirm driver function */
209 int r;
211 /* 1# arg: prompt */
212 r = KMessageBox::questionYesNoCancel(0,
213 str_to_qstring(mpdm_aget(a, 0)),
214 i18n("mp" VERSION));
216 switch (r) {
217 case KMessageBox::Yes:
218 r = 1;
219 break;
221 case KMessageBox::No:
222 r = 2;
223 break;
225 case KMessageBox::Cancel:
226 r = 0;
227 break;
230 return MPDM_I(r);
234 static mpdm_t kde4_drv_openfile(mpdm_t a, mpdm_t ctxt)
236 QString r;
237 char tmp[128];
239 getcwd(tmp, sizeof(tmp));
241 /* 1# arg: prompt */
242 r = KFileDialog::getOpenFileName(KUrl::fromPath(tmp), "*", 0,
243 str_to_qstring(mpdm_aget(a, 0)));
245 return qstring_to_str(r);
249 static mpdm_t kde4_drv_savefile(mpdm_t a, mpdm_t ctxt)
251 QString r;
252 char tmp[128];
254 getcwd(tmp, sizeof(tmp));
256 /* 1# arg: prompt */
257 r = KFileDialog::getSaveFileName(KUrl::fromPath(tmp), "*", 0,
258 str_to_qstring(mpdm_aget(a, 0)));
260 return qstring_to_str(r);
264 static mpdm_t kde4_drv_form(mpdm_t a, mpdm_t ctxt)
266 int n;
267 mpdm_t widget_list;
268 QWidget *qlist[100];
269 mpdm_t r;
271 KDialog *dialog = new KDialog(window);
273 dialog->setModal(true);
274 dialog->setButtons(KDialog::Ok | KDialog::Cancel);
276 widget_list = mpdm_aget(a, 0);
278 KVBox *vb = new KVBox(dialog);
279 dialog->setMainWidget(vb);
281 for (n = 0; n < mpdm_size(widget_list); n++) {
282 mpdm_t w = mpdm_aget(widget_list, n);
283 wchar_t *type;
284 mpdm_t t;
285 KHBox *hb = new KHBox(vb);
287 type = mpdm_string(mpdm_hget_s(w, L"type"));
289 if ((t = mpdm_hget_s(w, L"label")) != NULL) {
290 QLabel *ql = new QLabel(hb);
291 ql->setText(str_to_qstring(mpdm_gettext(t)));
294 t = mpdm_hget_s(w, L"value");
296 if (wcscmp(type, L"text") == 0) {
297 mpdm_t h;
298 QComboBox *ql = new QComboBox(hb);
300 ql->setEditable(true);
301 ql->setMinimumContentsLength(30);
302 ql->setMaxVisibleItems(8);
304 if (t != NULL)
305 ql->setEditText(str_to_qstring(t));
307 qlist[n] = ql;
309 if ((h = mpdm_hget_s(w, L"history")) != NULL) {
310 int i;
312 /* has history; fill it */
313 h = mp_get_history(h);
315 for (i = mpdm_size(h) - 1; i >= 0; i--)
316 ql->addItem(str_to_qstring(mpdm_aget(h, i)));
319 else
320 if (wcscmp(type, L"password") == 0) {
321 QLineEdit *ql = new QLineEdit(hb);
323 ql->setEchoMode(QLineEdit::Password);
325 qlist[n] = ql;
327 else
328 if (wcscmp(type, L"checkbox") == 0) {
329 QCheckBox *qc = new QCheckBox(hb);
331 if (mpdm_ival(t))
332 qc->setCheckState(Qt::Checked);
334 qlist[n] = qc;
336 else
337 if (wcscmp(type, L"list") == 0) {
338 int i;
339 QListWidget *ql = new QListWidget(hb);
340 ql->setMinimumWidth(480);
342 /* use a monospaced font */
343 ql->setFont(QFont(QString("Mono")));
345 mpdm_t l = mpdm_hget_s(w, L"list");
347 for (i = 0; i < mpdm_size(l); i++)
348 ql->addItem(str_to_qstring(mpdm_aget(l, i)));
350 ql->setCurrentRow(mpdm_ival(t));
352 qlist[n] = ql;
355 if (n == 0)
356 qlist[n]->setFocus(Qt::OtherFocusReason);
359 n = dialog->exec();
361 if (!n)
362 return NULL;
364 r = MPDM_A(mpdm_size(widget_list));
366 /* fill the return values */
367 for (n = 0; n < mpdm_size(widget_list); n++) {
368 mpdm_t w = mpdm_aget(widget_list, n);
369 mpdm_t v = NULL;
370 wchar_t *type;
372 type = mpdm_string(mpdm_hget_s(w, L"type"));
374 if (wcscmp(type, L"text") == 0) {
375 mpdm_t h;
376 QComboBox *ql = (QComboBox *) qlist[n];
378 v = qstring_to_str(ql->currentText());
380 /* if it has history, add to it */
381 if ((h = mpdm_hget_s(w, L"history")) != NULL &&
382 v != NULL && mpdm_cmp_s(v, L"") != 0) {
383 h = mp_get_history(h);
385 if (mpdm_cmp(v, mpdm_aget(h, -1)) != 0)
386 mpdm_push(h, v);
389 else
390 if (wcscmp(type, L"password") == 0) {
391 QLineEdit *ql = (QLineEdit *) qlist[n];
393 v = qstring_to_str(ql->text());
395 else
396 if (wcscmp(type, L"checkbox") == 0) {
397 QCheckBox *qb = (QCheckBox *) qlist[n];
399 v = MPDM_I(qb->checkState() == Qt::Checked);
401 else
402 if (wcscmp(type, L"list") == 0) {
403 QListWidget *ql = (QListWidget *) qlist[n];
405 v = MPDM_I(ql->currentRow());
408 mpdm_aset(r, v, n);
411 return r;
415 static mpdm_t kde4_drv_busy(mpdm_t a, mpdm_t ctxt)
417 return qt4_drv_busy(a);
421 static mpdm_t kde4_drv_main_loop(mpdm_t a, mpdm_t ctxt)
423 return qt4_drv_main_loop(a);
427 static mpdm_t kde4_drv_shutdown(mpdm_t a, mpdm_t ctxt)
429 return qt4_drv_shutdown(a);
433 static mpdm_t kde4_drv_clip_to_sys(mpdm_t a, mpdm_t ctxt)
435 return qt4_drv_clip_to_sys(a);
439 static mpdm_t kde4_drv_sys_to_clip(mpdm_t a, mpdm_t ctxt)
441 return qt4_drv_sys_to_clip(a);
445 static mpdm_t kde4_drv_timer(mpdm_t a, mpdm_t ctxt)
447 return qt4_drv_timer(a);
450 static void register_functions(void)
452 mpdm_t drv;
454 drv = mpdm_hget_s(mp, L"drv");
455 mpdm_hset_s(drv, L"main_loop", MPDM_X(kde4_drv_main_loop));
456 mpdm_hset_s(drv, L"shutdown", MPDM_X(kde4_drv_shutdown));
457 mpdm_hset_s(drv, L"clip_to_sys", MPDM_X(kde4_drv_clip_to_sys));
458 mpdm_hset_s(drv, L"sys_to_clip", MPDM_X(kde4_drv_sys_to_clip));
459 mpdm_hset_s(drv, L"update_ui", MPDM_X(kde4_drv_update_ui));
460 mpdm_hset_s(drv, L"timer", MPDM_X(kde4_drv_timer));
461 mpdm_hset_s(drv, L"busy", MPDM_X(kde4_drv_busy));
462 mpdm_hset_s(drv, L"alert", MPDM_X(kde4_drv_alert));
463 mpdm_hset_s(drv, L"confirm", MPDM_X(kde4_drv_confirm));
464 mpdm_hset_s(drv, L"openfile", MPDM_X(kde4_drv_openfile));
465 mpdm_hset_s(drv, L"savefile", MPDM_X(kde4_drv_savefile));
466 mpdm_hset_s(drv, L"form", MPDM_X(kde4_drv_form));
470 static mpdm_t kde4_drv_startup(mpdm_t a, mpdm_t ctxt)
471 /* driver initialization */
473 register_functions();
475 build_font(1);
476 build_colors();
478 window = new MPWindow();
479 window->show();
481 return NULL;
484 extern "C" Display * XOpenDisplay(char *);
486 extern "C" int kde4_drv_detect(int *argc, char ***argv)
488 mpdm_t drv;
489 KCmdLineOptions opts;
490 Display *x11_display;
491 int n;
493 for (n = 0; n < *argc; n++) {
494 if (strcmp(argv[0][n], "-txt") == 0 ||
495 strcmp(argv[0][n], "-h") == 0)
496 return 0;
499 /* try connecting directly to the Xserver */
500 if ((x11_display = XOpenDisplay((char *) NULL)) == NULL)
501 return 0;
503 KAboutData aboutData("mp", 0,
504 ki18n("Minimum Profit"), VERSION,
505 ki18n("A programmer's text editor"),
506 KAboutData::License_GPL,
507 ki18n("Copyright (c) 1991-2009 Angel Ortega"),
508 ki18n(""),
509 "http://triptico.com", "angel@triptico.com");
511 KCmdLineArgs::init(*argc, *argv, &aboutData);
513 /* command line options should be inserted here (I don't like this) */
514 opts.add("t {tag}", ki18n("Edits the file where tag is defined"));
515 opts.add("e {mpsl_code}", ki18n("Executes MPSL code"));
516 opts.add("f {mpsl_script}", ki18n("Executes MPSL script file"));
517 opts.add("d {directory}", ki18n("Sets working directory"));
518 opts.add("x {file}", ki18n("Open file in the hexadecimal viewer"));
519 opts.add(" +NNN", ki18n("Moves to line number NNN of last file"));
520 opts.add("txt", ki18n("Use text mode instead of GUI"));
521 opts.add("+[file(s)]", ki18n("Documents to open"));
522 KCmdLineArgs::addCmdLineOptions(opts);
524 /* this is where it crashes if no X server */
525 app = new KApplication(x11_display);
527 drv = mpdm_hget_s(mp, L"drv");
528 mpdm_hset_s(drv, L"id", MPDM_LS(L"kde4"));
529 mpdm_hset_s(drv, L"startup", MPDM_X(kde4_drv_startup));
531 return 1;
534 #include "mpv_kde4.moc"