Small changes in loggraph porting to Qt4
[vlp.git] / src / help / help.cpp
1 #include <QtGui/QApplication>
2 #include <QtGui/QMainWindow>
3 #include <Qt3Support/q3multilineedit.h>
4 #include <QtGui/QMenuBar>
5 // #include <qpopmenu.h>
6 #include <QtGui/QDialog>
7 #include <QtGui/QButtonGroup>
8 #include <QtGui/QLabel>
9 #include <QtGui/QLineEdit>
10 #include <Qt3Support/Q3ListBox>
11 #include <QtGui/QPushButton>
12 #include <QtGui/QRadioButton>
13 #include <QtCore/QList>
14 #include <QtCore/qfile.h>
15 #include <QtGui/qcombobox.h>
16 #include <QtGui/QToolTip>
17 #include <QtGui/QFont>
18 #include <QtGui/QPixmap>
19 #include <QtGui/QMessageBox>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <QtCore/QTextStream>
24 #include <QtCore/qstring.h>
25 #include <QtGui/QFileDialog>
26 #include <QtGui/QFontMetrics>
27 #include <QtGui/QPainter>
28 #include <QtGui/QScrollBar>
29
30
31 #define TAG_TEXT        0
32 #define TAG_OTHER       1
33
34 #define TAG_LINK        2 
35 #define TAG_ANCHOR      3 
36 #define TAG_BOLD_ON     4 
37 #define TAG_BOLD_OFF    5 
38 #define TAG_ITALIC_ON   6 
39 #define TAG_ITALIC_OFF  7 
40 #define TAG_BREAK       8 
41 #define TAG_LINE        9 
42 #define TAG_LINK_END    10 
43 #define TAG_LIST_ON     11
44 #define TAG_LIST_OFF    12
45 #define TAG_LIST_ITEM   13
46
47 #define PIX_HEIGHT      2000
48
49 char names[14][40] = {
50         "text", "other", "link", "anchor", "bold on",
51         "bold off", "italic on", "italic off", "break",
52         "line", "end link", "list on", "list off", "list item"
53 };
54
55 class Tag {
56 public:
57         Tag() {
58                 tag_type=0;
59                 strcpy(tag_label, "");
60                 strcpy(tag_link, "");
61                 strcpy(tag_text, "");
62         };
63         int tag_type;
64         char tag_label[255];
65         char tag_link[255];
66         char tag_text[255]; 
67         int x;
68         int y;
69         int w;
70         int h;
71 };
72
73 class HTMLAnalyzer {
74 public:
75         QList<Tag*> tags;
76         bool verbatim;
77
78         HTMLAnalyzer();
79
80         bool LoadFile(char*);
81         void AnalyzeTag(QString*);
82         void PackLinks();
83         void DumpList();
84         Tag *CheckTag(int, int);
85         Tag *FindAnchor(char*);
86 };
87
88 HTMLAnalyzer::HTMLAnalyzer()
89 {
90         tags.clear();
91         verbatim = FALSE;
92 }
93
94 bool HTMLAnalyzer::LoadFile(char *fname)
95 {
96         QFile f(fname);
97         QString poms, poms1;
98         int i;
99         Tag *pomt;
100         bool not_ended;
101
102         tags.clear();
103         if (!f.open(IO_ReadOnly))
104                 return(FALSE);
105
106         QTextStream fs(&f);
107
108         while (!fs.atEnd()) {
109                 poms = fs.readLine();
110                 while (poms.length()>0) {
111                         i = poms.find('<');
112                         if (i != -1) {
113                                 if (i > 1) {
114                                         poms1 = poms.left(i);
115                                         pomt = new Tag;
116                                         pomt->tag_type = TAG_TEXT;
117                                         if (!verbatim) {
118                                                 poms1 = poms1.simplifyWhiteSpace();
119                                         }
120                                                 
121                                         sprintf(pomt->tag_text, " %s", poms1.toStdString().c_str());
122                                         tags.append(pomt);
123                                 }
124                                 poms = poms.right(poms.length() - i);
125
126                                 i = poms.find('>');
127                                 if (i != -1) {
128                                         poms1 = poms.mid(1, i - 1);
129                                         AnalyzeTag(&poms1);
130                                         poms = poms.right(poms.length() - i -1);
131                                 } else {
132                                         not_ended = TRUE;
133                                         break;
134                                 }
135                         } else {
136                                 pomt = new Tag;
137                                 pomt->tag_type = TAG_TEXT;
138                                 if (!verbatim) 
139                                         poms=poms.simplifyWhiteSpace();
140                                 
141                                 sprintf(pomt->tag_text, " %s", poms.toStdString().c_str());
142                                 tags.append(pomt);
143                                 break;
144                         }
145                 }
146                 if (verbatim) {
147                         pomt = new Tag;
148                         pomt->tag_type = TAG_BREAK;
149                         tags.append(pomt);
150                 }
151         }
152         f.close();
153         return TRUE;
154 }
155
156 void HTMLAnalyzer::AnalyzeTag(QString *t)
157 {
158         Tag *pom;
159         int i;
160         QString poms, poms1;
161
162         *t = t->simplifyWhiteSpace();
163         pom = new Tag;
164
165         if ((t->toStdString().c_str()[0] != 'A') && (t->toStdString().c_str()[0] != 'a')) {
166                 *t = t->upper();
167                 if (strcmp(t->toStdString().c_str(), "B") ==0 ) {
168                         pom->tag_type = TAG_BOLD_ON;
169                 }
170                 else if (strcmp(t->toStdString().c_str(), "/B") == 0) {
171                         pom->tag_type = TAG_BOLD_OFF;
172                 }
173                 else if (strcmp(t->toStdString().c_str(), "I") == 0) {
174                         pom->tag_type = TAG_ITALIC_ON;
175                 }
176                 else if (strcmp(t->toStdString().c_str(), "/I") == 0) {
177                         pom->tag_type = TAG_ITALIC_OFF;
178                 }
179                 else if (strcmp(t->toStdString().c_str(), "BR") == 0) {
180                         pom->tag_type = TAG_BREAK;
181                 }
182                 else if (strcmp(t->toStdString().c_str(), "HR") == 0) {
183                         pom->tag_type = TAG_LINE;
184                 }
185                 else if (strcmp(t->toStdString().c_str(), "/A") == 0) {
186                         pom->tag_type = TAG_LINK_END;
187                 }
188                 else if (strcmp(t->toStdString().c_str(), "UL") == 0) {
189                         pom->tag_type = TAG_LIST_ON;
190                 }
191                 else if (strcmp(t->toStdString().c_str(), "/UL") == 0) {
192                         pom->tag_type = TAG_LIST_OFF;
193                 }
194                 else if (strcmp(t->toStdString().c_str(), "LI") == 0) {
195                         pom->tag_type = TAG_LIST_ITEM;
196                 }
197                 else if (strcmp(t->toStdString().c_str(), "PRE") == 0) {
198                         verbatim=TRUE;
199                 }
200                 else if (strcmp(t->toStdString().c_str(),"/PRE") == 0) {
201                         verbatim=FALSE;
202                 }
203         } else {
204          /*
205         'a' or 'A'
206         links
207         */
208                 i = t->find('=');
209                 if (i != -1) {
210                         poms = t->mid(2, i - 2);
211                         poms = poms.simplifyWhiteSpace();
212                         poms = poms.upper();
213                         poms1 = t->right(t->length() - i - 1);
214                         poms1 = poms1.simplifyWhiteSpace();
215
216                         if (poms == "HREF") {
217                                 pom->tag_type = TAG_LINK;
218                                 strcpy(pom->tag_link,poms1.toStdString().c_str());
219                         }
220                         else if (poms == "NAME") {
221                                 pom->tag_type = TAG_ANCHOR;
222                                 if (poms1[0] == '"')
223                                         poms1=poms1.right(poms1.length() - 1);
224                                 if (poms1[poms1.length() - 1] == '"')
225                                         poms1=poms1.left(poms1.length() - 1);
226                                 strcpy(pom->tag_label, poms1.toStdString().c_str());
227                         }
228                 }
229         }
230         tags.append(pom);
231 }
232
233 void HTMLAnalyzer::DumpList()
234 {
235         Tag *pom;
236         pom = tags.first();
237         while (pom != NULL) {
238                 fprintf(stderr, "%s:%s,%s,%s\n", names[pom->tag_type],
239                         pom->tag_text, pom->tag_link, pom->tag_label);
240                 pom=tags.takeFirst();
241         }
242 }
243
244 void HTMLAnalyzer::PackLinks()
245 {
246         Tag *pom,*pom1;
247         char s[255];
248
249         pom = tags.first();
250         while (pom!=NULL) {
251                 if ((pom->tag_type == TAG_LINK) ||
252                         (pom->tag_type == TAG_ANCHOR)) {
253                         pom1 = tags.takeFirst();
254                         strcpy(s, "");
255                         while ((pom1 != NULL) &&
256                                 (pom1->tag_type != TAG_LINK_END)) {
257                                 if (pom1->tag_type == TAG_TEXT)
258                                         strcat(s,pom1->tag_text);
259                                 tags.removeOne(pom1);
260                                 pom1 = tags.current();
261                         }
262                         strcpy(pom->tag_text,s); 
263                         tags.removeOne(pom1);
264                         pom = tags.current();
265                 } else {
266                         pom = tags.takeFirst();
267                 }
268         }
269 }
270
271
272 Tag *HTMLAnalyzer::CheckTag(int x,int y)
273 {
274         Tag *pom;
275         pom=tags.first();
276         while (pom != NULL) {
277                 if (pom->tag_type==TAG_LINK)
278                         if ((x >= pom->x) && (x <= pom->x + pom->w) &&
279                                 (y >= pom->y) && (y <= pom->y + pom->h)) {
280                                 return pom;
281                         }
282                 pom=tags.takeFirst();
283         }
284         return NULL;
285 }
286
287 Tag *HTMLAnalyzer::FindAnchor(char *name)
288 {
289         Tag *pom;
290         pom = tags.first();
291         while (pom != NULL) {
292                 if ((pom->tag_type == TAG_ANCHOR) &&
293                         (strcmp(pom->tag_label, name) == 0)) {
294                                 return(pom);
295                         }
296                 pom=tags.takeFirst();
297         }
298         return pom;
299 }
300 /********************************/
301
302 class QHTML: public QMainWindow {
303         Q_OBJECT
304 public:
305         QScrollBar *vscroll;
306         QMenuBar *bar;  
307         HTMLAnalyzer *analyzer;
308         QPixmap *map;
309         int cx,cy,oy,lstep,pstep;
310         bool Bold,Italic;
311         QFont *normal,*bold,*italic,*bold_italic,*actual_font;
312         char homedir[255];
313
314         QHTML(char*);
315         void DrawList();
316         virtual void paintEvent(QPaintEvent *ev);
317         virtual void resizeEvent(QResizeEvent *ev);
318         virtual void mousePressEvent(QMouseEvent *ev);
319 public slots:
320         void load();
321         void back();
322         void vscrolled(int);
323         void contents();
324         void user_guide();
325         void lang_guide();
326 };
327
328
329 QApplication *app;
330
331 QHTML::QHTML(char *d)
332 {
333         char s[255];
334
335         QFont f("Helvetica", 12, QFont::Bold);
336         normal = new QFont("Helvetica", 12, QFont::Normal);
337         bold = new QFont("Helvetica", 12, QFont::Bold);
338         italic = new QFont("Helvetica", 12, QFont::Normal, TRUE);
339         bold_italic = new QFont("Helvetica", 12, QFont::Bold, TRUE);
340         strcpy(homedir, d);
341
342         actual_font = normal;
343         
344         setWindowTitle("LOGLAN Help");
345
346         QMenu * contentsMenu = NULL;
347         menuBar()->addAction("File", this, SLOT(load()));
348         contentsMenu = menuBar()->addMenu("&Contents");
349         contentsMenu->addAction("Index", this, SLOT(contents()));
350         contentsMenu->addAction("User Guide", this, SLOT(user_guide()));
351         contentsMenu->addAction("Language reference", this, SLOT(lang_guide()));
352
353         menuBar()->addAction("Quit", app, SLOT(quit()));
354
355         analyzer = new HTMLAnalyzer;
356         map = new QPixmap(500, PIX_HEIGHT);
357         map->fill(backgroundColor());
358         resize(500, height());
359         setFixedSize(width(), height());
360         oy = 0;
361         lstep = 10;
362         pstep = height() - bar->height();
363         vscroll = new QScrollBar(0, PIX_HEIGHT, lstep, pstep, 0, QScrollBar::Vertical, this);
364         vscroll->setTracking(TRUE);  
365         vscroll->setGeometry(width() - 16, bar->height(), 16, height()-bar->height());
366         connect(vscroll, SIGNAL(valueChanged(int)), this, SLOT(vscrolled(int)));
367         sprintf(s, "%s/index.html", homedir);
368         analyzer->LoadFile(s);
369         analyzer->PackLinks();
370         DrawList();
371 }
372
373 void QHTML::vscrolled(int v)
374 {
375         oy = v;
376         repaint();
377 }
378
379 void QHTML::load()
380 {
381         QString s(QFileDialog::getOpenFileName(homedir, "*", this));
382         if (!s.isNull()) {
383                 vscroll->setValue(0); 
384                 analyzer->LoadFile((char*)s.ascii());
385                 analyzer->PackLinks();
386                 DrawList();
387         }
388 }
389
390 void QHTML::contents()
391 {
392         char ss[255];
393         sprintf(ss, "%s/index.html", homedir);
394         analyzer->LoadFile(ss);
395         analyzer->PackLinks();
396         DrawList(); 
397 }
398
399 void QHTML::user_guide()
400 {
401         char ss[255];
402         sprintf(ss, "%s/userg.html", homedir);
403         analyzer->LoadFile(ss);
404         analyzer->PackLinks();
405         DrawList(); 
406 }
407
408 void QHTML::lang_guide()
409 {
410         char ss[255];
411         sprintf(ss, "%s/langg.html", homedir);
412         analyzer->LoadFile(ss);
413         analyzer->PackLinks();
414         DrawList();
415 }
416
417 void QHTML::paintEvent(QPaintEvent *ev)
418 {
419         if (map != NULL) {
420                 bitBlt(this, 0, bar->height(), map, 0, oy,
421                                                 width() - 16, height() - 16);
422         }
423 }
424
425 void QHTML::resizeEvent(QResizeEvent *ev)
426 {
427         DrawList();
428 }
429
430 void QHTML::mousePressEvent(QMouseEvent *ev)
431 {
432         Tag *pom, *pom1;
433         QString poms;
434         char ss[255];
435
436         pom = analyzer->CheckTag(ev->x(), ev->y() + oy);
437         if (pom != NULL) {
438                 poms.sprintf(pom->tag_link);
439                 if (poms[0] == '"') 
440                         poms = poms.right(poms.length() - 1);
441                 if (poms[poms.length() - 1] == '"')
442                         poms=poms.left(poms.length() - 1);
443                 if (poms[0] == '#') {
444                         poms = poms.right(poms.length() - 1);
445                         pom1 = analyzer->FindAnchor((char*)poms.ascii());
446                         if (pom1 != NULL) {
447                                 vscroll->setValue(pom1->y);
448                         }
449                 } else {
450                         sprintf(ss, "%s/%s", homedir, poms.toStdString().c_str());
451                         analyzer->LoadFile(ss);
452                         analyzer->PackLinks();
453                         DrawList();
454                 }
455         }
456 }
457
458 /**
459  * @attention Currently not in use
460  */
461 void QHTML::back()
462 {
463 }
464
465 void QHTML::DrawList()
466 {
467         Tag *pom;
468         QPainter p;
469
470         if (!analyzer->tags.isEmpty()) {
471                 cx = 5;
472                 cy = 15;
473                 map->fill(backgroundColor());
474                 p.begin(map);
475
476                 pom = analyzer->tags.first();
477                 while (pom != NULL) {
478                         switch(pom->tag_type) {
479                         case TAG_TEXT:
480                                 p.setFont(*actual_font);
481                                 if (cx + p.fontMetrics().width(pom->tag_text) > 
482                                                                 width() - 16) {
483                                         cx = 5;
484                                         cy = cy + p.fontMetrics().height();
485                                 }
486                                 p.drawText(cx, cy, pom->tag_text);
487                                 cx = cx + p.fontMetrics().width(pom->tag_text);
488                                 break;
489                         case TAG_BREAK:
490                                 p.setFont(*actual_font);
491                                 cy = cy + p.fontMetrics().height();
492                                 cx = 5;
493                                 break;
494                         case TAG_ITALIC_ON:
495                                 if (actual_font == bold)
496                                         actual_font = bold_italic;
497                                 else 
498                                         actual_font = italic;
499
500                                 break;
501                         case TAG_ITALIC_OFF:
502                                 if (actual_font == bold_italic)
503                                         actual_font = bold;
504                                 else
505                                         actual_font = normal;
506
507                                 break;
508                         case TAG_BOLD_ON:
509                                 if (actual_font == italic)
510                                         actual_font = bold_italic;
511                                 else 
512                                         actual_font = bold;
513                                         
514                                 break;
515                         case TAG_BOLD_OFF:
516                                 if (actual_font == bold_italic)
517                                         actual_font = italic;
518                                 else 
519                                         actual_font = normal;
520                                         
521                                 break;
522                         case TAG_LINK:
523                                 p.setFont(*actual_font);
524                                 if (cx + p.fontMetrics().width(pom->tag_text) >
525                                                                 width() - 16) {
526                                         cx = 5;
527                                         cy = cy + p.fontMetrics().height();
528                                 }
529                                 p.setPen(QColor(255, 0, 0));
530                                 p.drawText(cx, cy, pom->tag_text);
531                                 pom->x = cx;
532                                 pom->y = cy + p.fontMetrics().height();
533                                 pom->w = p.fontMetrics().width(pom->tag_text);
534                                 pom->h = p.fontMetrics().height();
535                                 p.setPen(QColor(0, 0, 0));
536                                 cx = cx + p.fontMetrics().width(pom->tag_text);
537                                 break;
538                         case TAG_ANCHOR:
539                                 p.setFont(*actual_font);
540                                 if (cx + p.fontMetrics().width(pom->tag_text) >
541                                                                 width() - 16) {
542                                         cx = 5;
543                                         cy = cy + p.fontMetrics().height();
544                                 }
545                                 //p.setPen(QColor(0,255,0));
546                                 p.drawText(cx, cy, pom->tag_text);
547                                 pom->x = cx;
548                                 pom->y = cy - p.fontMetrics().height();
549                                 pom->w = p.fontMetrics().width(pom->tag_text);
550                                 pom->h = p.fontMetrics().height();
551                                 p.setPen(QColor(0, 0, 0));
552                                 cx=cx + p.fontMetrics().width(pom->tag_text);
553                                 break;
554                         case TAG_LIST_OFF:
555                         case TAG_LIST_ON:
556                                 p.setFont(*actual_font);
557                                 cx = 5;
558                                 cy = cy + p.fontMetrics().height();
559                                 break;
560                         case TAG_LIST_ITEM:p.setFont(*actual_font);
561                                 p.setBrush(QBrush(QColor(0, 0, 255)));
562                                 cx = 5;
563                                 cy = cy + p.fontMetrics().height();
564                                 p.drawPie(cx, cy - 5, 5, 5, 0, 5760); 
565                                 cx = cx + 15;
566                                 break;
567                         case TAG_LINE:
568                                 p.setFont(*actual_font);
569                                 cx = 5;
570                                 cy = cy + p.fontMetrics().height();
571                                 p.drawLine(cx, cy - 
572                                         (int)(p.fontMetrics().height() / 2),
573                                         width() - 16 - 5, cy -
574                                         (int)(p.fontMetrics().height() / 2));
575                                 cx = 5;
576                                 cy = cy + p.fontMetrics().height();
577                                 break;
578                         }
579                         pom = analyzer->tags.takeFirst();
580                 }
581                 p.end();
582                 repaint();
583         }
584 }
585
586 #include "help.moc"
587
588 int main( int argc, char **argv )
589 {
590         QString ps;
591
592         app = new QApplication(argc, argv);
593         if (argc == 2)
594                 ps.sprintf(argv[1]);
595         else
596                 ps.sprintf(".");
597         QHTML cfg((char*)ps.ascii());
598         //app->setStyle(WindowsStyle);
599 //      app->setMainWidget(&cfg);
600         cfg.show();
601         return app->exec();
602 }