1 // SCCS Id: @(#)qt_win.h 3.3 1999/11/19 2 // Copyright (c) Warwick Allison, 1999. 3 // NetHack may be freely redistributed. See license for details. 4 // 5 // Qt Binding for NetHack 3.3 6 // 7 // Unfortunately, this doesn't use Qt as well as I would like, 8 // primarily because NetHack is fundamentally a getkey-type 9 // program rather than being event driven (hence the ugly key 10 // and click buffer rather), but also because this is my first 11 // major application of Qt. 12 // 13 14 #ifndef qt_win_h 15 #define qt_win_h 16 17 #define QT_CLEAN_NAMESPACE 18 19 #include <qdialog.h> 20 #include <qpushbutton.h> 21 #include <qbuttongroup.h> 22 #include <qlabel.h> 23 #include <qlineedit.h> 24 #include <qapplication.h> 25 #include <qspinbox.h> 26 #include <qfile.h> 27 #include <qlistbox.h> 28 #include <qlistview.h> 29 #include <qmessagebox.h> 30 #include <qpixmap.h> 31 #include <qimage.h> 32 #include <qarray.h> 33 #include <qcombobox.h> 34 #include <qscrollview.h> 35 #include <qtableview.h> 36 37 #ifdef KDE 38 #include <kapp.h> 39 #include <ktopwidget.h> 40 #endif 41 42 #include "qt_clust.h" 43 44 class QVBox; 45 class QMenuBar; 46 class QRadioButton; 47 class NhPSListView; 48 49 ////////////////////////////////////////////////////////////// 50 // 51 // The beautiful, abstracted and well-modelled classes... 52 // 53 ////////////////////////////////////////////////////////////// 54 55 class NetHackQtGlyphs; 56 57 class NetHackQtLineEdit : public QLineEdit { 58 public: 59 NetHackQtLineEdit(); 60 NetHackQtLineEdit(QWidget* parent, const char* name); 61 62 void fakeEvent(int key, int ascii, int state); 63 }; 64 65 class NetHackQtSettings : public QDialog { 66 Q_OBJECT 67 public: 68 // Size of window - used to decide default sizes 69 NetHackQtSettings(int width, int height); 70 71 NetHackQtGlyphs& glyphs(); 72 const QFont& normalFont(); 73 const QFont& normalFixedFont(); 74 const QFont& largeFont(); 75 76 bool ynInMessages(); 77 78 signals: 79 void fontChanged(); 80 void tilesChanged(); 81 82 private: 83 QSpinBox tilewidth; 84 QSpinBox tileheight; 85 QLabel widthlbl; 86 QLabel heightlbl; 87 88 QComboBox fontsize; 89 90 QFont normal, normalfixed, large; 91 92 NetHackQtGlyphs* theglyphs; 93 94 private slots: 95 void resizeTiles(); 96 }; 97 98 class NetHackQtKeyBuffer { 99 public: 100 NetHackQtKeyBuffer(); 101 102 bool Empty() const; 103 bool Full() const; 104 105 void Put(int k, int ascii, int state); 106 void Put(const char* str); 107 int GetKey(); 108 int GetAscii(); 109 int GetState(); 110 111 int TopKey() const; 112 int TopAscii() const; 113 int TopState() const; 114 115 private: 116 enum { maxkey=64 }; 117 int key[maxkey]; 118 int ascii[maxkey]; 119 int state[maxkey]; 120 int in,out; 121 }; 122 123 class NetHackQtClickBuffer { 124 public: 125 NetHackQtClickBuffer(); 126 127 bool Empty() const; 128 bool Full() const; 129 130 void Put(int x, int y, int mod); 131 132 int NextX() const; 133 int NextY() const; 134 int NextMod() const; 135 136 void Get(); 137 138 private: 139 enum { maxclick=64 }; 140 struct ClickRec { 141 int x,y,mod; 142 } click[maxclick]; 143 int in,out; 144 }; 145 146 147 148 class NetHackQtPlayerSelector : private QDialog { 149 Q_OBJECT 150 public: 151 enum { R_None=-1, R_Quit=-2, R_Rand=-3 }; 152 153 NetHackQtPlayerSelector(NetHackQtKeyBuffer&); 154 155 protected: 156 virtual void done(int); 157 158 public slots: 159 void Quit(); 160 void Random(); 161 162 void selectName(const QString& n); 163 void selectRole(); 164 void selectRace(); 165 void setupOthers(); 166 void selectGender(int); 167 void selectAlignment(int); 168 169 public: 170 bool Choose(); 171 172 private: 173 NetHackQtKeyBuffer& keysource; 174 NhPSListView* role; 175 NhPSListView* race; 176 QRadioButton **gender; 177 QRadioButton **alignment; 178 }; 179 180 class NetHackQtStringRequestor : QDialog { 181 private: 182 QLabel prompt; 183 NetHackQtLineEdit input; 184 QPushButton* okay; 185 QPushButton* cancel; 186 NetHackQtKeyBuffer& keysource; 187 188 virtual void done(int); 189 190 public: 191 NetHackQtStringRequestor(NetHackQtKeyBuffer&, const char* p,const char* cancelstr="Cancel"); 192 void SetDefault(const char*); 193 bool Get(char* buffer, int maxchar=80); 194 virtual void resizeEvent(QResizeEvent*); 195 }; 196 197 class NetHackQtExtCmdRequestor : public QDialog { 198 Q_OBJECT 199 200 NetHackQtKeyBuffer& keysource; 201 202 public: 203 NetHackQtExtCmdRequestor(NetHackQtKeyBuffer& ks); 204 int get(); 205 206 private slots: 207 void cancel(); 208 void done(int i); 209 }; 210 211 212 class NetHackQtWindow { 213 public: 214 NetHackQtWindow(); 215 virtual ~NetHackQtWindow(); 216 217 virtual QWidget* Widget() =0; 218 219 virtual void Clear(); 220 virtual void Display(bool block); 221 virtual bool Destroy(); 222 virtual void CursorTo(int x,int y); 223 virtual void PutStr(int attr, const char* text); 224 virtual void StartMenu(); 225 virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr, 226 const char* str, bool presel); 227 virtual void EndMenu(const char* prompt); 228 virtual int SelectMenu(int how, MENU_ITEM_P **menu_list); 229 virtual void ClipAround(int x,int y); 230 virtual void PrintGlyph(int x,int y,int glyph); 231 virtual void UseRIP(int how); 232 }; 233 234 class NetHackQtGlyphs { 235 public: 236 NetHackQtGlyphs(); 237 width()238 int width() const { return size.width(); } height()239 int height() const { return size.height(); } 240 void resize(int w, int h); 241 242 void drawGlyph(QPainter&, int glyph, int pixelx, int pixely); 243 void drawCell(QPainter&, int glyph, int cellx, int celly); 244 245 private: 246 QImage img; 247 QPixmap pm; 248 QSize size; 249 int tiles_per_row; 250 }; 251 252 class BlackScrollView : public QScrollView { 253 public: BlackScrollView()254 BlackScrollView() 255 { 256 viewport()->setBackgroundColor(black); 257 } 258 }; 259 260 class NetHackQtMapWindow : public QWidget, public NetHackQtWindow { 261 Q_OBJECT 262 private: 263 NetHackQtClickBuffer& clicksink; 264 unsigned short glyph[ROWNO][COLNO]; Glyph(int x,int y)265 unsigned short& Glyph(int x, int y) { return glyph[y][x]; } 266 QPoint cursor; 267 BlackScrollView viewport; 268 QPixmap pet_annotation; 269 Clusterizer change; 270 QFont *rogue_font; 271 272 void Changed(int x,int y); 273 274 signals: 275 void resized(); 276 277 private slots: 278 void updateTiles(); 279 280 protected: 281 virtual void paintEvent(QPaintEvent*); 282 virtual void mousePressEvent(QMouseEvent*); 283 284 public: 285 NetHackQtMapWindow(NetHackQtClickBuffer& click_sink); 286 ~NetHackQtMapWindow(); 287 288 virtual QWidget* Widget(); 289 virtual bool Destroy(); 290 291 virtual void Clear(); 292 virtual void Display(bool block); 293 virtual void CursorTo(int x,int y); 294 virtual void PutStr(int attr, const char* text); 295 virtual void ClipAround(int x,int y); 296 virtual void PrintGlyph(int x,int y,int glyph); 297 298 void Scroll(int dx, int dy); 299 }; 300 301 class NetHackQtScrollText; 302 class NetHackQtMessageWindow : QObject, public NetHackQtWindow { 303 Q_OBJECT 304 public: 305 NetHackQtMessageWindow(); 306 ~NetHackQtMessageWindow(); 307 308 virtual QWidget* Widget(); 309 virtual void Clear(); 310 virtual void Display(bool block); 311 virtual void PutStr(int attr, const char* text); 312 313 void Scroll(int dx, int dy); 314 315 private: 316 NetHackQtScrollText* list; 317 bool changed; 318 319 private slots: 320 void updateFont(); 321 }; 322 323 class NetHackQtLabelledIcon : public QWidget { 324 public: 325 NetHackQtLabelledIcon(QWidget* parent, const char* label); 326 NetHackQtLabelledIcon(QWidget* parent, const char* label, const QPixmap& icon); 327 328 enum { NoNum=-99999 }; 329 void setLabel(const char*, bool lower=TRUE); // a string 330 void setLabel(const char*, long, const char* tail=""); // a number 331 void setLabel(const char*, long show_value, long comparative_value, const char* tail=""); 332 void setIcon(const QPixmap&); 333 virtual void setFont(const QFont&); 334 335 void highlightWhenChanging(); 336 void lowIsGood(); 337 void dissipateHighlight(); 338 339 virtual void show(); 340 341 protected: 342 void resizeEvent(QResizeEvent*); 343 344 private: 345 void initHighlight(); 346 void setAlignments(); 347 void highlight(const QPalette& highlight); 348 void unhighlight(); 349 350 bool low_is_good; 351 int prev_value; 352 int turn_count; /* last time the value changed */ 353 QPalette hl_good; 354 QPalette hl_bad; 355 356 QLabel* label; 357 QLabel* icon; 358 }; 359 360 class NetHackQtStatusWindow : QWidget, public NetHackQtWindow { 361 Q_OBJECT 362 public: 363 NetHackQtStatusWindow(); 364 365 virtual QWidget* Widget(); 366 367 virtual void Clear(); 368 virtual void Display(bool block); 369 virtual void CursorTo(int x,int y); 370 virtual void PutStr(int attr, const char* text); 371 372 void fadeHighlighting(); 373 374 protected: 375 void resizeEvent(QResizeEvent*); 376 377 private slots: 378 void doUpdate(); 379 380 private: 381 enum { hilight_time=1 }; 382 383 QPixmap p_str; 384 QPixmap p_dex; 385 QPixmap p_con; 386 QPixmap p_int; 387 QPixmap p_wis; 388 QPixmap p_cha; 389 390 QPixmap p_chaotic; 391 QPixmap p_neutral; 392 QPixmap p_lawful; 393 394 QPixmap p_satiated; 395 QPixmap p_hungry; 396 397 QPixmap p_confused; 398 QPixmap p_sick_fp; 399 QPixmap p_sick_il; 400 QPixmap p_blind; 401 QPixmap p_stunned; 402 QPixmap p_hallu; 403 404 QPixmap p_encumber[5]; 405 406 NetHackQtLabelledIcon name; 407 NetHackQtLabelledIcon dlevel; 408 409 NetHackQtLabelledIcon str; 410 NetHackQtLabelledIcon dex; 411 NetHackQtLabelledIcon con; 412 NetHackQtLabelledIcon intel; 413 NetHackQtLabelledIcon wis; 414 NetHackQtLabelledIcon cha; 415 416 NetHackQtLabelledIcon gold; 417 NetHackQtLabelledIcon hp; 418 NetHackQtLabelledIcon power; 419 NetHackQtLabelledIcon ac; 420 NetHackQtLabelledIcon level; 421 NetHackQtLabelledIcon exp; 422 NetHackQtLabelledIcon align; 423 424 NetHackQtLabelledIcon time; 425 NetHackQtLabelledIcon score; 426 427 NetHackQtLabelledIcon hunger; 428 NetHackQtLabelledIcon confused; 429 NetHackQtLabelledIcon sick_fp; 430 NetHackQtLabelledIcon sick_il; 431 NetHackQtLabelledIcon blind; 432 NetHackQtLabelledIcon stunned; 433 NetHackQtLabelledIcon hallu; 434 NetHackQtLabelledIcon encumber; 435 436 QFrame hline1; 437 QFrame hline2; 438 QFrame hline3; 439 440 int cursy; 441 442 bool first_set; 443 444 void nullOut(); 445 void updateStats(); 446 void checkTurnEvents(); 447 }; 448 449 class NetHackQtMenuDialog : public QDialog { 450 Q_OBJECT 451 public: 452 NetHackQtMenuDialog(); 453 454 void Accept(); 455 void Reject(); 456 void SetResult(int); 457 458 virtual void done(int); 459 460 protected: 461 void resizeEvent(QResizeEvent*); 462 463 signals: 464 void Resized(); 465 }; 466 467 468 class NetHackQtMenuWindow : public QTableView, public NetHackQtWindow { 469 Q_OBJECT 470 public: 471 NetHackQtMenuWindow(NetHackQtKeyBuffer&); 472 ~NetHackQtMenuWindow(); 473 474 virtual QWidget* Widget(); 475 476 virtual void StartMenu(); 477 virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr, 478 const char* str, bool presel); 479 virtual void EndMenu(const char* prompt); 480 virtual int SelectMenu(int how, MENU_ITEM_P **menu_list); 481 482 public slots: 483 void All(); 484 void ChooseNone(); 485 void Invert(); 486 void Search(); 487 488 void Layout(); 489 void ToggleSelect(int); 490 491 protected: 492 virtual void keyPressEvent(QKeyEvent*); 493 //virtual void mouseDoubleClickEvent(QMouseEvent*); 494 virtual void mousePressEvent(QMouseEvent*); 495 virtual void mouseReleaseEvent(QMouseEvent*); 496 virtual void mouseMoveEvent(QMouseEvent*); 497 virtual void focusOutEvent(QFocusEvent*); 498 virtual void focusInEvent(QFocusEvent*); 499 500 virtual void paintCell(QPainter*, int, int); 501 virtual int cellWidth(int col); 502 503 private: 504 struct MenuItem { 505 MenuItem(); 506 ~MenuItem(); 507 508 int glyph; 509 ANY_P identifier; 510 int attr; 511 const char* str; 512 int count; 513 char ch; 514 bool selected; 515 SelectableMenuItem516 bool Selectable() const { return identifier.a_void!=0; } 517 }; 518 519 QArray<MenuItem> item; 520 521 int itemcount; 522 int str_width; 523 bool str_fixed; 524 int next_accel; 525 526 NetHackQtKeyBuffer& keysource; 527 528 NetHackQtMenuDialog* dialog; 529 530 QPushButton* ok; 531 QPushButton* cancel; 532 QPushButton* all; 533 QPushButton* none; 534 QPushButton* invert; 535 QPushButton* search; 536 QLabel prompt; 537 538 int how; 539 540 bool has_glyphs; 541 542 int pressed; 543 bool was_sel; 544 }; 545 546 class NetHackQtTextListBox; 547 548 class NetHackQtRIP : public QWidget { 549 private: 550 static QPixmap* pixmap; 551 char** line; 552 int riplines; 553 554 public: 555 NetHackQtRIP(QWidget* parent); 556 557 void setLines(char** l, int n); 558 559 protected: 560 virtual void paintEvent(QPaintEvent* event); 561 }; 562 563 564 class NetHackQtTextWindow : public QDialog, public NetHackQtWindow { 565 Q_OBJECT 566 public: 567 NetHackQtTextWindow(NetHackQtKeyBuffer&); 568 ~NetHackQtTextWindow(); 569 570 virtual QWidget* Widget(); 571 572 virtual void Clear(); 573 virtual bool Destroy(); 574 virtual void Display(bool block); 575 virtual void PutStr(int attr, const char* text); 576 virtual void UseRIP(int how); 577 578 public slots: 579 void Search(); 580 581 protected: 582 virtual void done(int); 583 virtual void resizeEvent(QResizeEvent*); 584 virtual void keyPressEvent(QKeyEvent*); 585 586 private slots: 587 void doUpdate(); 588 589 private: 590 NetHackQtKeyBuffer& keysource; 591 592 bool use_rip; 593 bool str_fixed; 594 595 QPushButton ok; 596 QPushButton search; 597 NetHackQtTextListBox* lines; 598 599 NetHackQtRIP rip; 600 }; 601 602 class NetHackQtMenuOrTextWindow : public NetHackQtWindow { 603 private: 604 NetHackQtWindow* actual; 605 NetHackQtKeyBuffer& keysource; 606 607 public: 608 NetHackQtMenuOrTextWindow(NetHackQtKeyBuffer&); 609 610 virtual QWidget* Widget(); 611 612 // Text 613 virtual void Clear(); 614 virtual bool Destroy(); 615 virtual void Display(bool block); 616 virtual void PutStr(int attr, const char* text); 617 618 // Menu 619 virtual void StartMenu(); 620 virtual void AddMenu(int glyph, const ANY_P* identifier, char ch, char gch, int attr, 621 const char* str, bool presel); 622 virtual void EndMenu(const char* prompt); 623 virtual int SelectMenu(int how, MENU_ITEM_P **menu_list); 624 625 }; 626 627 class NetHackQtDelay : QObject { 628 private: 629 int msec; 630 631 public: 632 NetHackQtDelay(int ms); 633 void wait(); 634 virtual void timerEvent(QTimerEvent* timer); 635 }; 636 637 638 class NetHackQtInvUsageWindow : public QWidget { 639 public: 640 NetHackQtInvUsageWindow(QWidget* parent); 641 virtual void paintEvent(QPaintEvent*); 642 private: 643 void drawWorn(QPainter& painter, obj*, int x, int y, bool canbe=TRUE); 644 }; 645 646 // This class is the main widget for NetHack 647 // 648 // It is a collection of Message, Map, and Status windows. In the current 649 // version of nethack there is only one of each, and this class makes this 650 // assumption, not showing itself until all are inserted. 651 // 652 // This class simply knows how to layout such children sensibly. 653 // 654 // Since it is only responsible for layout, the class does not 655 // note the actual class of the windows. 656 // 657 #ifndef KDE 658 #include "qt_kde0.h" 659 #endif 660 661 class NetHackQtMainWindow : public KTopLevelWidget { 662 Q_OBJECT 663 public: 664 NetHackQtMainWindow(NetHackQtKeyBuffer&); 665 666 void AddMessageWindow(NetHackQtMessageWindow* window); 667 void AddMapWindow(NetHackQtMapWindow* window); 668 void AddStatusWindow(NetHackQtStatusWindow* window); 669 void RemoveWindow(NetHackQtWindow* window); 670 void updateInventory(); 671 672 void fadeHighlighting(); 673 674 public slots: 675 void doMenuItem(int); 676 677 protected: 678 virtual void resizeEvent(QResizeEvent*); 679 virtual void keyPressEvent(QKeyEvent*); 680 virtual void closeEvent(QCloseEvent*); 681 682 private slots: 683 void layout(); 684 685 private: 686 void ShowIfReady(); 687 688 #ifdef KDE 689 KMenuBar* menubar; 690 #else 691 QMenuBar* menubar; 692 #endif 693 NetHackQtMessageWindow* message; 694 NetHackQtMapWindow* map; 695 NetHackQtStatusWindow* status; 696 NetHackQtInvUsageWindow invusage; 697 698 NetHackQtKeyBuffer& keysink; 699 700 const char* *macro; 701 }; 702 703 class NetHackQtYnDialog : QDialog { 704 private: 705 const char* question; 706 const char* choices; 707 char def; 708 NetHackQtKeyBuffer& keysource; 709 710 protected: 711 virtual void keyPressEvent(QKeyEvent*); 712 virtual void done(int); 713 714 public: 715 NetHackQtYnDialog(NetHackQtKeyBuffer& keysource,const char*,const char*,char); 716 717 char Exec(); 718 }; 719 720 #ifdef KDE 721 #define NetHackQtBindBase KApplication 722 #else 723 #define NetHackQtBindBase QApplication 724 #endif 725 726 class NetHackQtBind : NetHackQtBindBase { 727 private: 728 // Single-instance preservation... 729 NetHackQtBind(int& argc, char** argv); 730 731 static NetHackQtBind* instance; 732 733 static NetHackQtKeyBuffer keybuffer; 734 static NetHackQtClickBuffer clickbuffer; 735 736 static NetHackQtMainWindow* main; 737 738 public: 739 static void qt_init_nhwindows(int* argc, char** argv); 740 static void qt_player_selection(); 741 static void qt_askname(); 742 static void qt_get_nh_event(); 743 static void qt_exit_nhwindows(const char *); 744 static void qt_suspend_nhwindows(const char *); 745 static void qt_resume_nhwindows(); 746 static winid qt_create_nhwindow(int type); 747 static void qt_clear_nhwindow(winid wid); 748 static void qt_display_nhwindow(winid wid, BOOLEAN_P block); 749 static void qt_destroy_nhwindow(winid wid); 750 static void qt_curs(winid wid, int x, int y); 751 static void qt_putstr(winid wid, int attr, const char *text); 752 static void qt_display_file(const char *filename, BOOLEAN_P must_exist); 753 static void qt_start_menu(winid wid); 754 static void qt_add_menu(winid wid, int glyph, 755 const ANY_P * identifier, CHAR_P ch, CHAR_P gch, int attr, 756 const char *str, BOOLEAN_P presel); 757 static void qt_end_menu(winid wid, const char *prompt); 758 static int qt_select_menu(winid wid, int how, MENU_ITEM_P **menu_list); 759 static void qt_update_inventory(); 760 static void qt_mark_synch(); 761 static void qt_wait_synch(); 762 763 static void qt_cliparound(int x, int y); 764 static void qt_cliparound_window(winid wid, int x, int y); 765 static void qt_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph); 766 static void qt_raw_print(const char *str); 767 static void qt_raw_print_bold(const char *str); 768 static int qt_nhgetch(); 769 static int qt_nh_poskey(int *x, int *y, int *mod); 770 static void qt_nhbell(); 771 static int qt_doprev_message(); 772 static char qt_yn_function(const char *question, const char *choices, CHAR_P def); 773 static void qt_getlin(const char *prompt, char *line); 774 static int qt_get_ext_cmd(); 775 static void qt_number_pad(int); 776 static void qt_delay_output(); 777 static void qt_start_screen(); 778 static void qt_end_screen(); 779 780 static void qt_outrip(winid wid, int how); 781 static int qt_kbhit(); 782 783 private: 784 virtual bool notify(QObject *receiver, QEvent *event); 785 }; 786 787 #endif 788