diff --git a/.gitignore b/.gitignore index 8530700..3f8b3ae 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ discord/ moc* /Attorney_Online_CC_resource.rc /attorney_online_cc_plugin_import.cpp + +*.autosave diff --git a/include/aoapplication.h b/include/aoapplication.h index 03aa01a..3d4cc0e 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -182,10 +182,16 @@ public: // from the config.ini. bool is_shakeandflash_enabled(); + // Returns whether evidence should be maintained ic + bool is_keepevi_enabled(); + // Returns the value of the maximum amount of lines the IC chatlog // may contain, from config.ini. int get_max_log_size(); + // Gets the punctuation delay modifier + int get_pundelay(); + // Returns whether the log should go upwards (new behaviour) // or downwards (vanilla behaviour). bool get_log_goes_downwards(); @@ -238,7 +244,11 @@ public: //Figure out if we can opus this or if we should fall back to wav QString get_sfx_suffix(QString sound_to_check); - // Can we use APNG for this? If not, fall back to a gif. + // figure out if we can find what prefix this song uses + QString get_music_prefix(QString song_to_check); + + // Can we use APNG for this? If not, WEBP? if not, GIF? If not, fall back to a + // gif. QString get_image_suffix(QString path_to_check); //Returns the value of p_search_line within target_tag and terminator_tag @@ -341,6 +351,15 @@ public: // Get the message for the CM for casing alerts. QString get_casing_can_host_cases(); + // Get if html for ic log is enabled + bool get_colored_iclog_enabled(); + + // Get if ic log mirror is enabled + bool get_iclmir_enabled(); + + // Get if only inline coloring should be shown in log + bool colorlog_restricted_enabled(); + private: const int RELEASE = 2; const int MAJOR_VERSION = 7; diff --git a/include/aomovie.h b/include/aomovie.h index 1f278bf..7ffad25 100644 --- a/include/aomovie.h +++ b/include/aomovie.h @@ -15,13 +15,16 @@ public: AOMovie(QWidget *p_parent, AOApplication *p_ao_app); void set_play_once(bool p_play_once); - void play(QString p_gif, QString p_char = "", QString p_custom_theme = ""); + void start_timer(int delay); + void play(QString p_gif, QString p_char = "", QString p_custom_theme = "", + int default_duration = 0); void combo_resize(int w, int h); void stop(); private: QMovie *m_movie; AOApplication *ao_app; + QTimer *timer; bool play_once = true; signals: @@ -29,6 +32,7 @@ signals: private slots: void frame_change(int n_frame); + void timer_done(); }; #endif // AOMOVIE_H diff --git a/include/aooptionsdialog.h b/include/aooptionsdialog.h index 233d079..90d3547 100644 --- a/include/aooptionsdialog.h +++ b/include/aooptionsdialog.h @@ -51,6 +51,8 @@ private: QCheckBox *ui_downwards_cb; QLabel *ui_length_lbl; QSpinBox *ui_length_spinbox; + QLabel *ui_pun_delay; + QSpinBox *ui_pun_delay_spinbox; QFrame *ui_log_names_divider; QLineEdit *ui_username_textbox; QLabel *ui_username_lbl; @@ -66,6 +68,12 @@ private: QLabel *ui_language_label; QComboBox *ui_language_combobox; + QLabel *ui_keepevi_lbl; + QCheckBox *ui_keepevi_cb; + + QLabel *ui_keepcobj_lbl; + QCheckBox *ui_keepcobj_cb; + QWidget *ui_callwords_tab; QWidget *ui_callwords_widget; QVBoxLayout *ui_callwords_layout; @@ -119,7 +127,18 @@ private: QLabel *ui_casing_cm_cases_lbl; QLineEdit *ui_casing_cm_cases_textbox; - bool needs_default_audiodev(); + QWidget *ui_other_tab; + QWidget *ui_other_widget; + QFormLayout *ui_other_layout; + QLabel *ui_other_fancy_icl_enabled_lb; + QCheckBox *ui_other_fancy_icl_enabled_cb; + QLabel *ui_other_mirror_icl_enabled_lb; + QCheckBox *ui_other_mirror_icl_enabled_cb; + + QLabel *ui_other_fancy_icl_limit_lb; + QCheckBox *ui_other_fancy_icl_limit_cb; + + bool needs_default_audiodev(); signals: diff --git a/include/aoscene.h b/include/aoscene.h index b58c0fd..29a44b0 100644 --- a/include/aoscene.h +++ b/include/aoscene.h @@ -21,7 +21,7 @@ private: QWidget *m_parent; QMovie *m_movie; AOApplication *ao_app; - + QString last_image; }; #endif // AOSCENE_H diff --git a/include/aotextarea.h b/include/aotextarea.h index d44596b..ae28564 100644 --- a/include/aotextarea.h +++ b/include/aotextarea.h @@ -12,7 +12,8 @@ class AOTextArea : public QTextBrowser public: AOTextArea(QWidget *p_parent = nullptr); - void append_chatmessage(QString p_name, QString p_message, QString p_colour); + void append_chatmessage(QString p_name, QString p_message, QString p_colour, + bool song); void append_error(QString p_message); private: diff --git a/include/chatlogpiece.h b/include/chatlogpiece.h index 34c5926..945a7bc 100644 --- a/include/chatlogpiece.h +++ b/include/chatlogpiece.h @@ -8,15 +8,17 @@ class chatlogpiece { public: chatlogpiece(); - chatlogpiece(QString p_name, QString p_showname, QString p_message, bool p_song); - chatlogpiece(QString p_name, QString p_showname, QString p_message, bool p_song, QDateTime p_datetime); - + chatlogpiece(QString p_name, QString p_showname, QString p_message, + bool p_song, int color); + chatlogpiece(QString p_name, QString p_showname, QString p_message, + bool p_song, int color, QDateTime p_datetime); QString get_name(); QString get_showname(); QString get_message(); bool get_is_song(); QDateTime get_datetime(); QString get_datetime_as_string(); + int get_chat_color(); QString get_full(); @@ -26,6 +28,7 @@ private: QString message; QDateTime datetime; bool is_song; + int color; }; #endif // CHATLOGPIECE_H diff --git a/include/courtroom.h b/include/courtroom.h index 74374c9..26380aa 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -223,15 +223,18 @@ public: //This function filters out the common CC inline text trickery, for appending to //the IC chatlog. - QString filter_ic_text(QString p_text); + QString filter_ic_text(QString p_text, bool skip_filter, int chat_color); //adds text to the IC chatlog. p_name first as bold then p_text then a newlin //this function keeps the chatlog scrolled to the top unless there's text selected // or the user isn't already scrolled to the top - void append_ic_text(QString p_text, QString p_name = "", bool is_songchange = false); + void append_ic_text(QString p_text, QString p_name = "", + bool is_songchange = false, bool force_filter = false, + bool skip_filter = false, int chat_color = 0); - //prints who played the song to IC chat and plays said song(if found on local filesystem) - //takes in a list where the first element is the song name and the second is the char id of who played it + // prints who played the song to IC chat and plays said song(if found on local + // filesystem) takes in a list where the first element is the song name and + // the second is the char id of who played it void handle_song(QStringList *p_contents); void play_preanim(bool noninterrupting); @@ -251,6 +254,7 @@ public: void check_connection_received(); void doScreenShake(); void doRealization(); + void refresh_iclog(bool skiplast); ~Courtroom(); @@ -331,6 +335,8 @@ private: bool rainbow_appended = false; bool blank_blip = false; + // The cursor to write with in mirror mode + QTextCursor *mirror_cursor; // Used for getting the current maximum blocks allowed in the IC chatlog. int log_maximum_blocks = 0; @@ -346,28 +352,27 @@ private: //keeps track of how long realization is visible(it's just a white square and should be visible less than a second) QTimer *realization_timer; - //times how long the blinking testimony should be shown(green one in the corner) - QTimer *testimony_show_timer; - //times how long the blinking testimony should be hidden - QTimer *testimony_hide_timer; - //every time point in char.inis times this equals the final time const int time_mod = 40; + // the amount of time non-animated objection/hold it/takethat images stay + // onscreen for in ms + const int shout_stay_time = 724; + + // the amount of time non-animated guilty/not guilty images stay onscreen for + // in ms + const int verdict_stay_time = 3000; + + // the amount of time non-animated witness testimony/cross-examination images + // stay onscreen for in ms + const int wtce_stay_time = 1500; + static const int chatmessage_size = 28; QString m_chatmessage[chatmessage_size]; bool chatmessage_is_empty = false; QString previous_ic_message = ""; - bool testimony_in_progress = false; - - //in milliseconds - const int testimony_show_time = 1500; - - //in milliseconds - const int testimony_hide_time = 500; - //char id, muted or not QMap mute_map; @@ -381,10 +386,21 @@ private: //state of text ticking, 0 = not yet ticking, 1 = ticking in progress, 2 = ticking done int text_state = 2; - //character id, which index of the char_list the player is + // characters we consider punctuation + const QString punctuation_chars = ".,?!:;"; + + // amount by which we multiply the delay when we parse punctuation chars + int punctuation_modifier = 2; + + // character id, which index of the char_list the player is int m_cid = -1; + // cid and this may differ in cases of ini-editing + + QString char_name = ""; int objection_state = 0; + bool keep_custom_objection = false; + QString objection_custom = ""; int realization_state = 0; int screenshake_state = 0; int text_color = 0; @@ -429,6 +445,8 @@ private: //whether the ooc chat is server or master chat, true is server bool server_ooc = true; + // Is AFK enabled + bool isafk = false; QString current_background = "default"; AOMusicPlayer *music_player; @@ -454,10 +472,17 @@ private: AOImage *ui_vp_chatbox; QLabel *ui_vp_showname; QTextEdit *ui_vp_message; - AOImage *ui_vp_testimony; - AOImage *ui_vp_realization; + AOMovie *ui_vp_realization; + AOMovie *ui_vp_testimony; AOMovie *ui_vp_wtce; AOMovie *ui_vp_objection; + void realization_done(); + + bool colorf_iclog = false; + bool mirror_iclog = false; + bool colorf_limit = false; + + bool keep_evidence_display = false; QTextEdit *ui_ic_chatlog; @@ -466,7 +491,7 @@ private: QListWidget *ui_mute_list; QListWidget *ui_area_list; - QListWidget *ui_music_list; + QTreeWidget *ui_music_list; AOButton *ui_pair_button; QListWidget *ui_pair_list; @@ -480,6 +505,8 @@ private: //QLineEdit *ui_area_password; QLineEdit *ui_music_search; + QString music_search_par = ""; + QString area_search_par = ""; QWidget *ui_emotes; QVector ui_emote_list; @@ -527,6 +554,8 @@ private: AOButton *ui_screenshake; AOButton *ui_mute; + QMenu *custom_obj_menu; + AOButton *ui_defense_plus; AOButton *ui_defense_minus; @@ -589,11 +618,6 @@ public slots: void objection_done(); void preanim_done(); - void realization_done(); - - void show_testimony(); - void hide_testimony(); - void mod_called(QString p_ip); void case_called(QString msg, bool def, bool pro, bool jud, bool jur, bool steno, bool witness); @@ -611,8 +635,9 @@ private slots: void on_ooc_return_pressed(); + void on_music_search_keypr(); void on_music_search_edited(QString p_text); - void on_music_list_double_clicked(QModelIndex p_model); + void on_music_list_double_clicked(QTreeWidgetItem *p_item, int column); void on_area_list_double_clicked(QModelIndex p_model); void select_emote(int p_id); @@ -641,6 +666,7 @@ private slots: void on_objection_clicked(); void on_take_that_clicked(); void on_custom_objection_clicked(); + void ShowContextMenu(const QPoint &pos); void on_realization_clicked(); void on_screenshake_clicked(); diff --git a/include/lobby.h b/include/lobby.h index d32debe..0dca3d6 100644 --- a/include/lobby.h +++ b/include/lobby.h @@ -38,7 +38,7 @@ public: QString get_chatlog(); int get_selected_server(); void enable_connect_button(); - + void check_update(); void set_loading_value(int p_value); bool public_servers_selected = true; diff --git a/src/aoapplication.cpp b/src/aoapplication.cpp index 6213acd..8546566 100644 --- a/src/aoapplication.cpp +++ b/src/aoapplication.cpp @@ -135,6 +135,7 @@ void AOApplication::server_disconnected() { if (courtroom_constructed) { + beep(); call_notice(tr("Disconnected from server.")); construct_lobby(); destruct_courtroom(); diff --git a/src/aocharmovie.cpp b/src/aocharmovie.cpp index ca0d152..f0dad42 100644 --- a/src/aocharmovie.cpp +++ b/src/aocharmovie.cpp @@ -154,9 +154,6 @@ void AOCharMovie::sfx_two_network_boogaloo() void AOCharMovie::movie_ticker() { - if(apng){ - ticker->start(m_movie->nextFrameDelay()); - } if(m_movie->currentFrameNumber() == m_movie->frameCount() - 1) { delete m_movie; diff --git a/src/aomovie.cpp b/src/aomovie.cpp index edf5bdb..bb8e53d 100644 --- a/src/aomovie.cpp +++ b/src/aomovie.cpp @@ -1,7 +1,7 @@ #include "aomovie.h" -#include "file_functions.h" #include "courtroom.h" +#include "file_functions.h" #include "misc_functions.h" AOMovie::AOMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent) @@ -11,55 +11,80 @@ AOMovie::AOMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent) m_movie = new QMovie(); this->setMovie(m_movie); - + timer = new QTimer(this); + timer->setTimerType(Qt::PreciseTimer); + timer->setSingleShot(true); connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frame_change(int))); + connect(timer, SIGNAL(timeout()), this, SLOT(timer_done())); } void AOMovie::set_play_once(bool p_play_once) { play_once = p_play_once; } +void AOMovie::start_timer(int delay) { timer->start(delay); } -void AOMovie::play(QString p_gif, QString p_char, QString p_custom_theme) +void AOMovie::play(QString p_gif, QString p_char, QString p_custom_theme, + int duration) { + m_movie->stop(); + // this->timer_done(); + QString shout_path = p_gif; + QList pathlist; - QString gif_path; - - QString custom_path; - if (p_gif == "custom") - custom_path = ao_app->get_image_suffix(ao_app->get_character_path(p_char, p_gif)); + if (ao_app->get_character_path(p_char, p_gif) + .contains( + "custom_objections")) // checks if the file is located within the + // folder of custom objections + pathlist << ao_app->get_character_path( + p_char, + p_gif); // get_image_suffix is unecessery as it is already given. + else if (p_gif == "custom") + pathlist << ao_app->get_image_suffix( + ao_app->get_character_path(p_char, p_gif)); else - custom_path = ao_app->get_image_suffix(ao_app->get_character_path(p_char, p_gif + "_bubble")); + pathlist << ao_app->get_image_suffix( + ao_app->get_character_path(p_char, p_gif + "_bubble")); - QString misc_path = ao_app->get_base_path() + "misc/" + p_custom_theme + "/" + p_gif + "_bubble.gif"; - QString custom_theme_path = ao_app->get_custom_theme_path(p_custom_theme, p_gif + ".gif"); + QString misc_path = ao_app->get_base_path() + "misc/" + p_custom_theme + "/" + + p_gif + "_bubble.gif"; + QString custom_theme_path = + ao_app->get_custom_theme_path(p_custom_theme, p_gif + ".gif"); QString theme_path = ao_app->get_theme_path(p_gif + ".gif"); QString default_theme_path = ao_app->get_default_theme_path(p_gif + ".gif"); QString placeholder_path = ao_app->get_theme_path("placeholder.gif"); - QString default_placeholder_path = ao_app->get_default_theme_path("placeholder.gif"); + QString default_placeholder_path = + ao_app->get_default_theme_path("placeholder.gif"); - if (file_exists(custom_path)) - gif_path = custom_path; - else if (file_exists(misc_path)) - gif_path = misc_path; - else if (file_exists(custom_theme_path)) - gif_path = custom_theme_path; - else if (file_exists(theme_path)) - gif_path = theme_path; - else if (file_exists(default_theme_path)) - gif_path = default_theme_path; - else if (file_exists(placeholder_path)) - gif_path = placeholder_path; - else if (file_exists(default_placeholder_path)) - gif_path = default_placeholder_path; - else - gif_path = ""; + pathlist << ao_app->get_image_suffix(ao_app->get_base_path() + "misc/" + + p_custom_theme + "/" + p_gif + "_bubble") + << // Misc path + ao_app->get_image_suffix( + ao_app->get_custom_theme_path(p_custom_theme, p_gif)) + << // Custom theme path + ao_app->get_image_suffix(ao_app->get_theme_path(p_gif)) << // Theme path + ao_app->get_image_suffix(ao_app->get_default_theme_path(p_gif)) + << // Default theme path + ao_app->get_image_suffix(ao_app->get_theme_path("placeholder")) + << // Placeholder path + ao_app->get_image_suffix(ao_app->get_default_theme_path( + "placeholder")); // Default placeholder path - m_movie->setFileName(gif_path); + for (QString path : pathlist) { + if (file_exists(path)) { + shout_path = path; + break; + } + } + m_movie->setFileName(shout_path); + if (m_movie->loopCount() == 0) + play_once = true; this->show(); m_movie->start(); + if (m_movie->frameCount() == 0 && duration > 0) + timer->start(duration); } void AOMovie::stop() @@ -70,16 +95,20 @@ void AOMovie::stop() void AOMovie::frame_change(int n_frame) { - if (n_frame == (m_movie->frameCount() - 1) && play_once) - { - //we need this or else the last frame wont show - delay(m_movie->nextFrameDelay()); + // If it's a "static movie" (only one frame - png image), we can't change + // frames - ignore this function (use timer instead). If the frame didn't + // reach the last frame or the movie is continuous, don't stop the movie. + if (m_movie->frameCount() == 0 || n_frame < (m_movie->frameCount() - 1) || + !play_once) + return; + // we need this or else the last frame wont show + timer->start(m_movie->nextFrameDelay()); +} - this->stop(); - - //signal connected to courtroom object, let it figure out what to do - done(); - } +void AOMovie::timer_done() +{ + this->stop(); + done(); } void AOMovie::combo_resize(int w, int h) diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp index 55f7583..3be8466 100644 --- a/src/aooptionsdialog.cpp +++ b/src/aooptionsdialog.cpp @@ -1,596 +1,731 @@ #include "aooptionsdialog.h" #include "aoapplication.h" -AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) : QDialog(parent) +AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) + : QDialog(parent) { - ao_app = p_ao_app; + ao_app = p_ao_app; + + // Setting up the basics. + // setAttribute(Qt::WA_DeleteOnClose); + setWindowTitle(tr("Settings")); + resize(398, 360); + + ui_settings_buttons = new QDialogButtonBox(this); + + QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed); + sizePolicy1.setHorizontalStretch(0); + sizePolicy1.setVerticalStretch(0); + sizePolicy1.setHeightForWidth( + ui_settings_buttons->sizePolicy().hasHeightForWidth()); + ui_settings_buttons->setSizePolicy(sizePolicy1); + ui_settings_buttons->setOrientation(Qt::Horizontal); + ui_settings_buttons->setStandardButtons(QDialogButtonBox::Cancel | + QDialogButtonBox::Save); - // Setting up the basics. - // setAttribute(Qt::WA_DeleteOnClose); - setWindowTitle(tr("Settings")); - resize(398, 320); + QObject::connect(ui_settings_buttons, SIGNAL(accepted()), this, + SLOT(save_pressed())); + QObject::connect(ui_settings_buttons, SIGNAL(rejected()), this, + SLOT(discard_pressed())); + + // We'll stop updates so that the window won't flicker while it's being made. + setUpdatesEnabled(false); - ui_settings_buttons = new QDialogButtonBox(this); + // First of all, we want a tabbed dialog, so let's add some layout. + ui_vertical_layout = new QVBoxLayout(this); + ui_settings_tabs = new QTabWidget(this); - QSizePolicy sizePolicy1(QSizePolicy::Expanding, QSizePolicy::Fixed); - sizePolicy1.setHorizontalStretch(0); - sizePolicy1.setVerticalStretch(0); - sizePolicy1.setHeightForWidth(ui_settings_buttons->sizePolicy().hasHeightForWidth()); - ui_settings_buttons->setSizePolicy(sizePolicy1); - ui_settings_buttons->setOrientation(Qt::Horizontal); - ui_settings_buttons->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Save); + ui_vertical_layout->addWidget(ui_settings_tabs); + ui_vertical_layout->addWidget(ui_settings_buttons); - QObject::connect(ui_settings_buttons, SIGNAL(accepted()), this, SLOT(save_pressed())); - QObject::connect(ui_settings_buttons, SIGNAL(rejected()), this, SLOT(discard_pressed())); + // Let's add the tabs one by one. + + // + // GAMEPLAY + // + + ui_gameplay_tab = new QWidget(); + ui_settings_tabs->addTab(ui_gameplay_tab, tr("Gameplay")); - // We'll stop updates so that the window won't flicker while it's being made. - setUpdatesEnabled(false); + ui_form_layout_widget = new QWidget(ui_gameplay_tab); + ui_form_layout_widget->setGeometry(QRect(10, 10, 361, 240)); - // First of all, we want a tabbed dialog, so let's add some layout. - ui_vertical_layout = new QVBoxLayout(this); - ui_settings_tabs = new QTabWidget(this); + ui_gameplay_form = new QFormLayout(ui_form_layout_widget); + ui_gameplay_form->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignVCenter); + ui_gameplay_form->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignTop); + ui_gameplay_form->setContentsMargins(0, 0, 0, 0); - ui_vertical_layout->addWidget(ui_settings_tabs); - ui_vertical_layout->addWidget(ui_settings_buttons); + ui_theme_label = new QLabel(ui_form_layout_widget); + ui_theme_label->setText(tr("Theme:")); + ui_theme_label->setToolTip( + tr("Sets the theme used in-game. If the new theme changes " + "the lobby's look as well, you'll need to reload the " + "lobby for the changes to take effect, such as by joining " + "a server and leaving it.")); + ui_gameplay_form->setWidget(0, QFormLayout::LabelRole, ui_theme_label); - // Let's add the tabs one by one. - // First, we'll start with 'Gameplay'. - ui_gameplay_tab = new QWidget(); - ui_settings_tabs->addTab(ui_gameplay_tab, tr("Gameplay")); + ui_theme_combobox = new QComboBox(ui_form_layout_widget); - ui_form_layout_widget = new QWidget(ui_gameplay_tab); - ui_form_layout_widget->setGeometry(QRect(10, 10, 361, 211)); + // Fill the combobox with the names of the themes. + QDirIterator it(p_ao_app->get_base_path() + "themes", QDir::Dirs, + QDirIterator::NoIteratorFlags); + while (it.hasNext()) { + QString actualname = QDir(it.next()).dirName(); + if (actualname != "." && actualname != "..") + ui_theme_combobox->addItem(actualname); + if (actualname == p_ao_app->read_theme()) + ui_theme_combobox->setCurrentIndex(ui_theme_combobox->count() - 1); + } - ui_gameplay_form = new QFormLayout(ui_form_layout_widget); - ui_gameplay_form->setLabelAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); - ui_gameplay_form->setFormAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); - ui_gameplay_form->setContentsMargins(0, 0, 0, 0); + ui_gameplay_form->setWidget(0, QFormLayout::FieldRole, ui_theme_combobox); - ui_theme_label = new QLabel(ui_form_layout_widget); - ui_theme_label->setText(tr("Theme:")); - ui_theme_label->setToolTip(tr("Sets the theme used in-game. If the new theme changes " - "the lobby's look as well, you'll need to reload the " - "lobby for the changes to take effect, such as by joining " - "a server and leaving it.")); - ui_gameplay_form->setWidget(0, QFormLayout::LabelRole, ui_theme_label); + ui_theme_log_divider = new QFrame(ui_form_layout_widget); + ui_theme_log_divider->setMidLineWidth(0); + ui_theme_log_divider->setFrameShape(QFrame::HLine); + ui_theme_log_divider->setFrameShadow(QFrame::Sunken); - ui_theme_combobox = new QComboBox(ui_form_layout_widget); + ui_gameplay_form->setWidget(1, QFormLayout::FieldRole, ui_theme_log_divider); - // Fill the combobox with the names of the themes. - QDirIterator it(p_ao_app->get_base_path() + "themes", QDir::Dirs, QDirIterator::NoIteratorFlags); - while (it.hasNext()) - { - QString actualname = QDir(it.next()).dirName(); - if (actualname != "." && actualname != "..") - ui_theme_combobox->addItem(actualname); - if (actualname == p_ao_app->read_theme()) - ui_theme_combobox->setCurrentIndex(ui_theme_combobox->count()-1); - } + ui_downwards_lbl = new QLabel(ui_form_layout_widget); + ui_downwards_lbl->setText(tr("Log goes downwards:")); + ui_downwards_lbl->setToolTip( + tr("If ticked, new messages will appear at " + "the bottom (like the OOC chatlog). The traditional " + "(AO1) behaviour is equivalent to this being unticked.")); - ui_gameplay_form->setWidget(0, QFormLayout::FieldRole, ui_theme_combobox); + ui_gameplay_form->setWidget(2, QFormLayout::LabelRole, ui_downwards_lbl); - ui_theme_log_divider = new QFrame(ui_form_layout_widget); - ui_theme_log_divider->setMidLineWidth(0); - ui_theme_log_divider->setFrameShape(QFrame::HLine); - ui_theme_log_divider->setFrameShadow(QFrame::Sunken); + ui_downwards_cb = new QCheckBox(ui_form_layout_widget); + ui_downwards_cb->setChecked(p_ao_app->get_log_goes_downwards()); - ui_gameplay_form->setWidget(1, QFormLayout::FieldRole, ui_theme_log_divider); + ui_gameplay_form->setWidget(2, QFormLayout::FieldRole, ui_downwards_cb); - ui_downwards_lbl = new QLabel(ui_form_layout_widget); - ui_downwards_lbl->setText(tr("Log goes downwards:")); - ui_downwards_lbl->setToolTip(tr("If ticked, new messages will appear at " - "the bottom (like the OOC chatlog). The traditional " - "(AO1) behaviour is equivalent to this being unticked.")); + ui_length_lbl = new QLabel(ui_form_layout_widget); + ui_length_lbl->setText(tr("Log length:")); + ui_length_lbl->setToolTip(tr( + "The amount of messages the IC chatlog will keep before " + "deleting older messages. A value of 0 or below counts as 'infinite'.")); - ui_gameplay_form->setWidget(2, QFormLayout::LabelRole, ui_downwards_lbl); + ui_gameplay_form->setWidget(3, QFormLayout::LabelRole, ui_length_lbl); - ui_downwards_cb = new QCheckBox(ui_form_layout_widget); - ui_downwards_cb->setChecked(p_ao_app->get_log_goes_downwards()); + ui_length_spinbox = new QSpinBox(ui_form_layout_widget); + ui_length_spinbox->setMaximum(10000); + ui_length_spinbox->setValue(p_ao_app->get_max_log_size()); + + ui_gameplay_form->setWidget(3, QFormLayout::FieldRole, ui_length_spinbox); - ui_gameplay_form->setWidget(2, QFormLayout::FieldRole, ui_downwards_cb); + ui_log_names_divider = new QFrame(ui_form_layout_widget); + ui_log_names_divider->setFrameShape(QFrame::HLine); + ui_log_names_divider->setFrameShadow(QFrame::Sunken); - ui_length_lbl = new QLabel(ui_form_layout_widget); - ui_length_lbl->setText(tr("Log length:")); - ui_length_lbl->setToolTip(tr("The amount of messages the IC chatlog will keep before " - "deleting older messages. A value of 0 or below counts as 'infinite'.")); + ui_gameplay_form->setWidget(4, QFormLayout::FieldRole, ui_log_names_divider); - ui_gameplay_form->setWidget(3, QFormLayout::LabelRole, ui_length_lbl); + ui_username_lbl = new QLabel(ui_form_layout_widget); + ui_username_lbl->setText(tr("Default username:")); + ui_username_lbl->setToolTip( + tr("Your OOC name will be automatically set to this value " + "when you join a server.")); - ui_length_spinbox = new QSpinBox(ui_form_layout_widget); - ui_length_spinbox->setMaximum(10000); - ui_length_spinbox->setValue(p_ao_app->get_max_log_size()); + ui_gameplay_form->setWidget(5, QFormLayout::LabelRole, ui_username_lbl); - ui_gameplay_form->setWidget(3, QFormLayout::FieldRole, ui_length_spinbox); + ui_username_textbox = new QLineEdit(ui_form_layout_widget); + ui_username_textbox->setMaxLength(30); + ui_username_textbox->setText(p_ao_app->get_default_username()); - ui_log_names_divider = new QFrame(ui_form_layout_widget); - ui_log_names_divider->setFrameShape(QFrame::HLine); - ui_log_names_divider->setFrameShadow(QFrame::Sunken); + ui_gameplay_form->setWidget(5, QFormLayout::FieldRole, ui_username_textbox); - ui_gameplay_form->setWidget(4, QFormLayout::FieldRole, ui_log_names_divider); + ui_showname_lbl = new QLabel(ui_form_layout_widget); + ui_showname_lbl->setText(tr("Custom shownames:")); + ui_showname_lbl->setToolTip( + tr("Gives the default value for the in-game 'Custom shownames' " + "tickbox, which in turn determines whether the client should " + "display custom in-character names.")); - ui_username_lbl = new QLabel(ui_form_layout_widget); - ui_username_lbl->setText(tr("Default username:")); - ui_username_lbl->setToolTip(tr("Your OOC name will be automatically set to this value " - "when you join a server.")); + ui_gameplay_form->setWidget(6, QFormLayout::LabelRole, ui_showname_lbl); + + ui_showname_cb = new QCheckBox(ui_form_layout_widget); + ui_showname_cb->setChecked(p_ao_app->get_showname_enabled_by_default()); + + ui_gameplay_form->setWidget(6, QFormLayout::FieldRole, ui_showname_cb); + + ui_net_divider = new QFrame(ui_form_layout_widget); + ui_net_divider->setFrameShape(QFrame::HLine); + ui_net_divider->setFrameShadow(QFrame::Sunken); + + ui_gameplay_form->setWidget(7, QFormLayout::FieldRole, ui_net_divider); + + ui_ms_lbl = new QLabel(ui_form_layout_widget); + ui_ms_lbl->setText(tr("Backup MS:")); + ui_ms_lbl->setToolTip( + tr("If the built-in server lookups fail, the game will try the " + "address given here and use it as a backup master server address.")); - ui_gameplay_form->setWidget(5, QFormLayout::LabelRole, ui_username_lbl); + ui_gameplay_form->setWidget(8, QFormLayout::LabelRole, ui_ms_lbl); - ui_username_textbox = new QLineEdit(ui_form_layout_widget); - ui_username_textbox->setMaxLength(30); - ui_username_textbox->setText(p_ao_app->get_default_username()); + QSettings *configini = ao_app->configini; + ui_ms_textbox = new QLineEdit(ui_form_layout_widget); + ui_ms_textbox->setText(configini->value("master", "").value()); - ui_gameplay_form->setWidget(5, QFormLayout::FieldRole, ui_username_textbox); + ui_gameplay_form->setWidget(8, QFormLayout::FieldRole, ui_ms_textbox); + + ui_discord_lbl = new QLabel(ui_form_layout_widget); + ui_discord_lbl->setText(tr("Discord:")); + ui_discord_lbl->setToolTip( + tr("Allows others on Discord to see what server you are in, " + "what character are you playing, and how long you have " + "been playing for.")); - ui_showname_lbl = new QLabel(ui_form_layout_widget); - ui_showname_lbl->setText(tr("Custom shownames:")); - ui_showname_lbl->setToolTip(tr("Gives the default value for the in-game 'Custom shownames' " - "tickbox, which in turn determines whether the client should " - "display custom in-character names.")); + ui_gameplay_form->setWidget(9, QFormLayout::LabelRole, ui_discord_lbl); - ui_gameplay_form->setWidget(6, QFormLayout::LabelRole, ui_showname_lbl); + ui_discord_cb = new QCheckBox(ui_form_layout_widget); + ui_discord_cb->setChecked(ao_app->is_discord_enabled()); - ui_showname_cb = new QCheckBox(ui_form_layout_widget); - ui_showname_cb->setChecked(p_ao_app->get_showname_enabled_by_default()); + ui_gameplay_form->setWidget(9, QFormLayout::FieldRole, ui_discord_cb); - ui_gameplay_form->setWidget(6, QFormLayout::FieldRole, ui_showname_cb); + ui_epilepsy_lbl = new QLabel(ui_form_layout_widget); + ui_epilepsy_lbl->setText(tr("Allow Shake/Flash:")); + ui_epilepsy_lbl->setToolTip( + tr("Allows screenshaking and flashing. Disable this if you have concerns " + "or issues with photosensitivity and/or seizures.")); + + ui_gameplay_form->setWidget(10, QFormLayout::LabelRole, ui_epilepsy_lbl); + + ui_epilepsy_cb = new QCheckBox(ui_form_layout_widget); + ui_epilepsy_cb->setChecked(ao_app->is_shakeandflash_enabled()); + + ui_gameplay_form->setWidget(10, QFormLayout::FieldRole, ui_epilepsy_cb); + + ui_language_label = new QLabel(ui_form_layout_widget); + ui_language_label->setText(tr("Language:")); + ui_language_label->setToolTip( + tr("Sets the language if you don't want to use your system language.")); + ui_gameplay_form->setWidget(11, QFormLayout::LabelRole, ui_language_label); + + ui_language_combobox = new QComboBox(ui_form_layout_widget); + ui_language_combobox->addItem( + configini->value("language", " ").value() + + " - Keep current setting"); + ui_language_combobox->addItem(" - Default"); + ui_language_combobox->addItem("en - English"); + ui_language_combobox->addItem("de - Deutsch"); + ui_language_combobox->addItem("es - Español"); + ui_language_combobox->addItem("pt - Português"); + ui_language_combobox->addItem("jp - 日本語"); + ui_language_combobox->addItem("ru - Русский"); + ui_gameplay_form->setWidget(11, QFormLayout::FieldRole, ui_language_combobox); + + // Here we start the callwords tab. + ui_callwords_tab = new QWidget(); + ui_settings_tabs->addTab(ui_callwords_tab, tr("Callwords")); + + ui_callwords_widget = new QWidget(ui_callwords_tab); + ui_callwords_widget->setGeometry(QRect(10, 10, 361, 211)); + + ui_callwords_layout = new QVBoxLayout(ui_callwords_widget); + ui_callwords_layout->setContentsMargins(0, 0, 0, 0); + + ui_callwords_textbox = new QPlainTextEdit(ui_callwords_widget); + QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + sizePolicy.setHorizontalStretch(0); + sizePolicy.setVerticalStretch(0); + sizePolicy.setHeightForWidth( + ui_callwords_textbox->sizePolicy().hasHeightForWidth()); + ui_callwords_textbox->setSizePolicy(sizePolicy); + + // Let's fill the callwords text edit with the already present callwords. + ui_callwords_textbox->document()->clear(); + foreach (QString callword, p_ao_app->get_call_words()) { + ui_callwords_textbox->appendPlainText(callword); + } + + ui_callwords_layout->addWidget(ui_callwords_textbox); + + ui_callwords_explain_lbl = new QLabel(ui_callwords_widget); + ui_callwords_explain_lbl->setWordWrap(true); + ui_callwords_explain_lbl->setText( + tr("Enter as many callwords as you would like. These " + "are case insensitive. Make sure to leave every callword in its own " + "line!
Do not leave a line with a space at the end -- you will be " + "alerted everytime someone uses a space in their " + "messages.")); + + ui_callwords_layout->addWidget(ui_callwords_explain_lbl); + + // The audio tab. + ui_audio_tab = new QWidget(); + ui_settings_tabs->addTab(ui_audio_tab, tr("Audio")); + + ui_audio_widget = new QWidget(ui_audio_tab); + ui_audio_widget->setGeometry(QRect(10, 10, 361, 211)); + + ui_audio_layout = new QFormLayout(ui_audio_widget); + ui_audio_layout->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignVCenter); + ui_audio_layout->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignTop); + ui_audio_layout->setContentsMargins(0, 0, 0, 0); + + ui_audio_device_lbl = new QLabel(ui_audio_widget); + ui_audio_device_lbl->setText(tr("Audio device:")); + ui_audio_device_lbl->setToolTip(tr("Sets the audio device for all sounds.")); + + ui_audio_layout->setWidget(0, QFormLayout::LabelRole, ui_audio_device_lbl); + + ui_audio_device_combobox = new QComboBox(ui_audio_widget); + + // Let's fill out the combobox with the available audio devices. Or don't if + // there is no audio + if (needs_default_audiodev()) { + + ui_audio_device_combobox->addItem("default"); + } +#ifdef BASSAUDIO + BASS_DEVICEINFO info; + int a = 0; + for (a = 0; BASS_GetDeviceInfo(a, &info); a++) { + ui_audio_device_combobox->addItem(info.name); + if (p_ao_app->get_audio_output_device() == info.name) + ui_audio_device_combobox->setCurrentIndex( + ui_audio_device_combobox->count() - 1); + } +#elif defined QTAUDIO + foreach (const QAudioDeviceInfo &deviceInfo, + QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { + ui_audio_device_combobox->addItem(deviceInfo.deviceName()); + if (p_ao_app->get_audio_output_device() == deviceInfo.deviceName()) + ui_audio_device_combobox->setCurrentIndex( + ui_audio_device_combobox->count() - 1); + } +#endif + ui_audio_layout->setWidget(0, QFormLayout::FieldRole, + ui_audio_device_combobox); + + ui_audio_volume_divider = new QFrame(ui_audio_widget); + ui_audio_volume_divider->setFrameShape(QFrame::HLine); + ui_audio_volume_divider->setFrameShadow(QFrame::Sunken); + + ui_audio_layout->setWidget(1, QFormLayout::FieldRole, + ui_audio_volume_divider); + + ui_music_volume_lbl = new QLabel(ui_audio_widget); + ui_music_volume_lbl->setText(tr("Music:")); + ui_music_volume_lbl->setToolTip(tr("Sets the music's default volume.")); + + ui_audio_layout->setWidget(2, QFormLayout::LabelRole, ui_music_volume_lbl); + + ui_music_volume_spinbox = new QSpinBox(ui_audio_widget); + ui_music_volume_spinbox->setValue(p_ao_app->get_default_music()); + ui_music_volume_spinbox->setMaximum(100); + ui_music_volume_spinbox->setSuffix("%"); - ui_net_divider = new QFrame(ui_form_layout_widget); - ui_net_divider->setFrameShape(QFrame::HLine); - ui_net_divider->setFrameShadow(QFrame::Sunken); + ui_audio_layout->setWidget(2, QFormLayout::FieldRole, + ui_music_volume_spinbox); + + ui_sfx_volume_lbl = new QLabel(ui_audio_widget); + ui_sfx_volume_lbl->setText(tr("SFX:")); + ui_sfx_volume_lbl->setToolTip( + tr("Sets the SFX's default volume. " + "Interjections and actual sound effects count as 'SFX'.")); + + ui_audio_layout->setWidget(3, QFormLayout::LabelRole, ui_sfx_volume_lbl); + + ui_sfx_volume_spinbox = new QSpinBox(ui_audio_widget); + ui_sfx_volume_spinbox->setValue(p_ao_app->get_default_sfx()); + ui_sfx_volume_spinbox->setMaximum(100); + ui_sfx_volume_spinbox->setSuffix("%"); + + ui_audio_layout->setWidget(3, QFormLayout::FieldRole, ui_sfx_volume_spinbox); + + ui_blips_volume_lbl = new QLabel(ui_audio_widget); + ui_blips_volume_lbl->setText(tr("Blips:")); + ui_blips_volume_lbl->setToolTip( + tr("Sets the volume of the blips, the talking sound effects.")); + + ui_audio_layout->setWidget(4, QFormLayout::LabelRole, ui_blips_volume_lbl); + + ui_blips_volume_spinbox = new QSpinBox(ui_audio_widget); + ui_blips_volume_spinbox->setValue(p_ao_app->get_default_blip()); + ui_blips_volume_spinbox->setMaximum(100); + ui_blips_volume_spinbox->setSuffix("%"); - ui_gameplay_form->setWidget(7, QFormLayout::FieldRole, ui_net_divider); + ui_audio_layout->setWidget(4, QFormLayout::FieldRole, + ui_blips_volume_spinbox); - ui_ms_lbl = new QLabel(ui_form_layout_widget); - ui_ms_lbl->setText(tr("Backup MS:")); - ui_ms_lbl->setToolTip(tr("If the built-in server lookups fail, the game will try the " - "address given here and use it as a backup master server address.")); + ui_volume_blip_divider = new QFrame(ui_audio_widget); + ui_volume_blip_divider->setFrameShape(QFrame::HLine); + ui_volume_blip_divider->setFrameShadow(QFrame::Sunken); - ui_gameplay_form->setWidget(8, QFormLayout::LabelRole, ui_ms_lbl); + ui_audio_layout->setWidget(5, QFormLayout::FieldRole, ui_volume_blip_divider); - QSettings* configini = ao_app->configini; - ui_ms_textbox = new QLineEdit(ui_form_layout_widget); - ui_ms_textbox->setText(configini->value("master", "").value()); + ui_bliprate_lbl = new QLabel(ui_audio_widget); + ui_bliprate_lbl->setText(tr("Blip rate:")); + ui_bliprate_lbl->setToolTip( + tr("Sets the delay between playing the blip sounds.")); - ui_gameplay_form->setWidget(8, QFormLayout::FieldRole, ui_ms_textbox); + ui_audio_layout->setWidget(6, QFormLayout::LabelRole, ui_bliprate_lbl); - ui_discord_lbl = new QLabel(ui_form_layout_widget); - ui_discord_lbl->setText(tr("Discord:")); - ui_discord_lbl->setToolTip(tr("Allows others on Discord to see what server you are in, " - "what character are you playing, and how long you have " - "been playing for.")); + ui_bliprate_spinbox = new QSpinBox(ui_audio_widget); + ui_bliprate_spinbox->setValue(p_ao_app->read_blip_rate()); + ui_bliprate_spinbox->setMinimum(1); - ui_gameplay_form->setWidget(9, QFormLayout::LabelRole, ui_discord_lbl); + ui_audio_layout->setWidget(6, QFormLayout::FieldRole, ui_bliprate_spinbox); - ui_discord_cb = new QCheckBox(ui_form_layout_widget); - ui_discord_cb->setChecked(ao_app->is_discord_enabled()); + ui_blank_blips_lbl = new QLabel(ui_audio_widget); + ui_blank_blips_lbl->setText(tr("Blank blips:")); + ui_blank_blips_lbl->setToolTip( + tr("If true, the game will play a blip sound even " + "when a space is 'being said'.")); - ui_gameplay_form->setWidget(9, QFormLayout::FieldRole, ui_discord_cb); + ui_audio_layout->setWidget(7, QFormLayout::LabelRole, ui_blank_blips_lbl); - ui_epilepsy_lbl = new QLabel(ui_form_layout_widget); - ui_epilepsy_lbl->setText(tr("Allow Shake/Flash:")); - ui_epilepsy_lbl->setToolTip(tr("Allows screenshaking and flashing. Disable this if you have concerns or issues with photosensitivity and/or seizures.")); + ui_blank_blips_cb = new QCheckBox(ui_audio_widget); + ui_blank_blips_cb->setChecked(p_ao_app->get_blank_blip()); - ui_gameplay_form->setWidget(10, QFormLayout::LabelRole, ui_epilepsy_lbl); + ui_audio_layout->setWidget(7, QFormLayout::FieldRole, ui_blank_blips_cb); - ui_epilepsy_cb = new QCheckBox(ui_form_layout_widget); - ui_epilepsy_cb->setChecked(ao_app->is_shakeandflash_enabled()); + ui_loopsfx_lbl = new QLabel(ui_audio_widget); + ui_loopsfx_lbl->setText(tr("Enable Looping SFX:")); + ui_loopsfx_lbl->setToolTip(tr("If true, the game will allow looping sound " + "effects to play on preanimations.")); - ui_gameplay_form->setWidget(10, QFormLayout::FieldRole, ui_epilepsy_cb); + ui_audio_layout->setWidget(8, QFormLayout::LabelRole, ui_loopsfx_lbl); - ui_language_label = new QLabel(ui_form_layout_widget); - ui_language_label->setText(tr("Language:")); - ui_language_label->setToolTip(tr("Sets the language if you don't want to use your system language.")); - ui_gameplay_form->setWidget(11, QFormLayout::LabelRole, ui_language_label); + ui_loopsfx_cb = new QCheckBox(ui_audio_widget); + ui_loopsfx_cb->setChecked(p_ao_app->get_looping_sfx()); - ui_language_combobox = new QComboBox(ui_form_layout_widget); - ui_language_combobox->addItem(configini->value("language", " ").value() + " - Keep current setting"); - ui_language_combobox->addItem(" - Default"); - ui_language_combobox->addItem("en - English"); - ui_language_combobox->addItem("de - Deutsch"); - ui_language_combobox->addItem("es - Español"); - ui_language_combobox->addItem("pt - Português"); - ui_language_combobox->addItem("jp - 日本語"); - ui_language_combobox->addItem("ru - Русский"); - ui_gameplay_form->setWidget(11, QFormLayout::FieldRole, ui_language_combobox); + ui_audio_layout->setWidget(8, QFormLayout::FieldRole, ui_loopsfx_cb); - // Here we start the callwords tab. - ui_callwords_tab = new QWidget(); - ui_settings_tabs->addTab(ui_callwords_tab, tr("Callwords")); + ui_objectmusic_lbl = new QLabel(ui_audio_widget); + ui_objectmusic_lbl->setText(tr("Kill Music On Objection:")); + ui_objectmusic_lbl->setToolTip( + tr("If true, the game will stop music when someone objects, like in the " + "actual games.")); - ui_callwords_widget = new QWidget(ui_callwords_tab); - ui_callwords_widget->setGeometry(QRect(10, 10, 361, 211)); + ui_audio_layout->setWidget(9, QFormLayout::LabelRole, ui_objectmusic_lbl); - ui_callwords_layout = new QVBoxLayout(ui_callwords_widget); - ui_callwords_layout->setContentsMargins(0,0,0,0); + ui_objectmusic_cb = new QCheckBox(ui_audio_widget); + ui_objectmusic_cb->setChecked(p_ao_app->get_objectmusic()); - ui_callwords_textbox = new QPlainTextEdit(ui_callwords_widget); - QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - sizePolicy.setHorizontalStretch(0); - sizePolicy.setVerticalStretch(0); - sizePolicy.setHeightForWidth(ui_callwords_textbox->sizePolicy().hasHeightForWidth()); - ui_callwords_textbox->setSizePolicy(sizePolicy); + ui_audio_layout->setWidget(9, QFormLayout::FieldRole, ui_objectmusic_cb); - // Let's fill the callwords text edit with the already present callwords. - ui_callwords_textbox->document()->clear(); - foreach (QString callword, p_ao_app->get_call_words()) { - ui_callwords_textbox->appendPlainText(callword); - } + // + // CASING + // + ui_casing_tab = new QWidget(); + ui_settings_tabs->addTab(ui_casing_tab, tr("Casing")); - ui_callwords_layout->addWidget(ui_callwords_textbox); + ui_casing_widget = new QWidget(ui_casing_tab); + ui_casing_widget->setGeometry(QRect(10, 10, 361, 211)); - ui_callwords_explain_lbl = new QLabel(ui_callwords_widget); - ui_callwords_explain_lbl->setWordWrap(true); - ui_callwords_explain_lbl->setText(tr("Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!
Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.")); + ui_casing_layout = new QFormLayout(ui_casing_widget); + ui_casing_layout->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignVCenter); + ui_casing_layout->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignTop); + ui_casing_layout->setContentsMargins(0, 0, 0, 0); - ui_callwords_layout->addWidget(ui_callwords_explain_lbl); + // -- SERVER SUPPORTS CASING - // The audio tab. - ui_audio_tab = new QWidget(); - ui_settings_tabs->addTab(ui_audio_tab, tr("Audio")); + ui_casing_supported_lbl = new QLabel(ui_casing_widget); + if (ao_app->casing_alerts_enabled) + ui_casing_supported_lbl->setText(tr("This server supports case alerts.")); + else + ui_casing_supported_lbl->setText( + tr("This server does not support case alerts.")); + ui_casing_supported_lbl->setToolTip(tr("Pretty self-explanatory.")); - ui_audio_widget = new QWidget(ui_audio_tab); - ui_audio_widget->setGeometry(QRect(10, 10, 361, 211)); + ui_casing_layout->setWidget(0, QFormLayout::FieldRole, + ui_casing_supported_lbl); - ui_audio_layout = new QFormLayout(ui_audio_widget); - ui_audio_layout->setLabelAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); - ui_audio_layout->setFormAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); - ui_audio_layout->setContentsMargins(0, 0, 0, 0); + // -- CASE ANNOUNCEMENTS - ui_audio_device_lbl = new QLabel(ui_audio_widget); - ui_audio_device_lbl->setText(tr("Audio device:")); - ui_audio_device_lbl->setToolTip(tr("Sets the audio device for all sounds.")); + ui_casing_enabled_lbl = new QLabel(ui_casing_widget); + ui_casing_enabled_lbl->setText(tr("Casing:")); + ui_casing_enabled_lbl->setToolTip( + tr("If checked, you will get alerts about case " + "announcements.")); - ui_audio_layout->setWidget(0, QFormLayout::LabelRole, ui_audio_device_lbl); + ui_casing_layout->setWidget(1, QFormLayout::LabelRole, ui_casing_enabled_lbl); - ui_audio_device_combobox = new QComboBox(ui_audio_widget); + ui_casing_enabled_cb = new QCheckBox(ui_casing_widget); + ui_casing_enabled_cb->setChecked(ao_app->get_casing_enabled()); - // Let's fill out the combobox with the available audio devices. Or don't if there is no audio - if (needs_default_audiodev()) - { + ui_casing_layout->setWidget(1, QFormLayout::FieldRole, ui_casing_enabled_cb); - ui_audio_device_combobox->addItem("default"); + // -- DEFENSE ANNOUNCEMENTS - } - #ifdef BASSAUDIO - BASS_DEVICEINFO info; - int a = 0; - for (a = 0; BASS_GetDeviceInfo(a, &info); a++) - { - ui_audio_device_combobox->addItem(info.name); - if (p_ao_app->get_audio_output_device() == info.name) - ui_audio_device_combobox->setCurrentIndex(ui_audio_device_combobox->count()-1); - } - #elif defined QTAUDIO - foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) - { - ui_audio_device_combobox->addItem(deviceInfo.deviceName()); - if (p_ao_app->get_audio_output_device() == deviceInfo.deviceName()) - ui_audio_device_combobox->setCurrentIndex(ui_audio_device_combobox->count()-1); - } - #endif - ui_audio_layout->setWidget(0, QFormLayout::FieldRole, ui_audio_device_combobox); + ui_casing_def_lbl = new QLabel(ui_casing_widget); + ui_casing_def_lbl->setText(tr("Defense:")); + ui_casing_def_lbl->setToolTip(tr("If checked, you will get alerts about case " + "announcements if a defense spot is open.")); - ui_audio_volume_divider = new QFrame(ui_audio_widget); - ui_audio_volume_divider->setFrameShape(QFrame::HLine); - ui_audio_volume_divider->setFrameShadow(QFrame::Sunken); + ui_casing_layout->setWidget(2, QFormLayout::LabelRole, ui_casing_def_lbl); - ui_audio_layout->setWidget(1, QFormLayout::FieldRole, ui_audio_volume_divider); + ui_casing_def_cb = new QCheckBox(ui_casing_widget); + ui_casing_def_cb->setChecked(ao_app->get_casing_defence_enabled()); - ui_music_volume_lbl = new QLabel(ui_audio_widget); - ui_music_volume_lbl->setText(tr("Music:")); - ui_music_volume_lbl->setToolTip(tr("Sets the music's default volume.")); + ui_casing_layout->setWidget(2, QFormLayout::FieldRole, ui_casing_def_cb); - ui_audio_layout->setWidget(2, QFormLayout::LabelRole, ui_music_volume_lbl); + // -- PROSECUTOR ANNOUNCEMENTS - ui_music_volume_spinbox = new QSpinBox(ui_audio_widget); - ui_music_volume_spinbox->setValue(p_ao_app->get_default_music()); - ui_music_volume_spinbox->setMaximum(100); - ui_music_volume_spinbox->setSuffix("%"); + ui_casing_pro_lbl = new QLabel(ui_casing_widget); + ui_casing_pro_lbl->setText(tr("Prosecution:")); + ui_casing_pro_lbl->setToolTip( + tr("If checked, you will get alerts about case " + "announcements if a prosecutor spot is open.")); - ui_audio_layout->setWidget(2, QFormLayout::FieldRole, ui_music_volume_spinbox); + ui_casing_layout->setWidget(3, QFormLayout::LabelRole, ui_casing_pro_lbl); - ui_sfx_volume_lbl = new QLabel(ui_audio_widget); - ui_sfx_volume_lbl->setText(tr("SFX:")); - ui_sfx_volume_lbl->setToolTip(tr("Sets the SFX's default volume. " - "Interjections and actual sound effects count as 'SFX'.")); + ui_casing_pro_cb = new QCheckBox(ui_casing_widget); + ui_casing_pro_cb->setChecked(ao_app->get_casing_prosecution_enabled()); - ui_audio_layout->setWidget(3, QFormLayout::LabelRole, ui_sfx_volume_lbl); + ui_casing_layout->setWidget(3, QFormLayout::FieldRole, ui_casing_pro_cb); - ui_sfx_volume_spinbox = new QSpinBox(ui_audio_widget); - ui_sfx_volume_spinbox->setValue(p_ao_app->get_default_sfx()); - ui_sfx_volume_spinbox->setMaximum(100); - ui_sfx_volume_spinbox->setSuffix("%"); + // -- JUDGE ANNOUNCEMENTS - ui_audio_layout->setWidget(3, QFormLayout::FieldRole, ui_sfx_volume_spinbox); + ui_casing_jud_lbl = new QLabel(ui_casing_widget); + ui_casing_jud_lbl->setText(tr("Judge:")); + ui_casing_jud_lbl->setToolTip(tr("If checked, you will get alerts about case " + "announcements if the judge spot is open.")); - ui_blips_volume_lbl = new QLabel(ui_audio_widget); - ui_blips_volume_lbl->setText(tr("Blips:")); - ui_blips_volume_lbl->setToolTip(tr("Sets the volume of the blips, the talking sound effects.")); + ui_casing_layout->setWidget(4, QFormLayout::LabelRole, ui_casing_jud_lbl); - ui_audio_layout->setWidget(4, QFormLayout::LabelRole, ui_blips_volume_lbl); + ui_casing_jud_cb = new QCheckBox(ui_casing_widget); + ui_casing_jud_cb->setChecked(ao_app->get_casing_judge_enabled()); - ui_blips_volume_spinbox = new QSpinBox(ui_audio_widget); - ui_blips_volume_spinbox->setValue(p_ao_app->get_default_blip()); - ui_blips_volume_spinbox->setMaximum(100); - ui_blips_volume_spinbox->setSuffix("%"); + ui_casing_layout->setWidget(4, QFormLayout::FieldRole, ui_casing_jud_cb); - ui_audio_layout->setWidget(4, QFormLayout::FieldRole, ui_blips_volume_spinbox); + // -- JUROR ANNOUNCEMENTS - ui_volume_blip_divider = new QFrame(ui_audio_widget); - ui_volume_blip_divider->setFrameShape(QFrame::HLine); - ui_volume_blip_divider->setFrameShadow(QFrame::Sunken); + ui_casing_jur_lbl = new QLabel(ui_casing_widget); + ui_casing_jur_lbl->setText(tr("Juror:")); + ui_casing_jur_lbl->setToolTip(tr("If checked, you will get alerts about case " + "announcements if a juror spot is open.")); - ui_audio_layout->setWidget(5, QFormLayout::FieldRole, ui_volume_blip_divider); + ui_casing_layout->setWidget(5, QFormLayout::LabelRole, ui_casing_jur_lbl); - ui_bliprate_lbl = new QLabel(ui_audio_widget); - ui_bliprate_lbl->setText(tr("Blip rate:")); - ui_bliprate_lbl->setToolTip(tr("Sets the delay between playing the blip sounds.")); + ui_casing_jur_cb = new QCheckBox(ui_casing_widget); + ui_casing_jur_cb->setChecked(ao_app->get_casing_juror_enabled()); - ui_audio_layout->setWidget(6, QFormLayout::LabelRole, ui_bliprate_lbl); + ui_casing_layout->setWidget(5, QFormLayout::FieldRole, ui_casing_jur_cb); - ui_bliprate_spinbox = new QSpinBox(ui_audio_widget); - ui_bliprate_spinbox->setValue(p_ao_app->read_blip_rate()); - ui_bliprate_spinbox->setMinimum(1); + // -- STENO ANNOUNCEMENTS - ui_audio_layout->setWidget(6, QFormLayout::FieldRole, ui_bliprate_spinbox); + ui_casing_steno_lbl = new QLabel(ui_casing_widget); + ui_casing_steno_lbl->setText(tr("Stenographer:")); + ui_casing_steno_lbl->setToolTip( + tr("If checked, you will get alerts about case " + "announcements if a stenographer spot is open.")); - ui_blank_blips_lbl = new QLabel(ui_audio_widget); - ui_blank_blips_lbl->setText(tr("Blank blips:")); - ui_blank_blips_lbl->setToolTip(tr("If true, the game will play a blip sound even " - "when a space is 'being said'.")); + ui_casing_layout->setWidget(6, QFormLayout::LabelRole, ui_casing_steno_lbl); - ui_audio_layout->setWidget(7, QFormLayout::LabelRole, ui_blank_blips_lbl); + ui_casing_steno_cb = new QCheckBox(ui_casing_widget); + ui_casing_steno_cb->setChecked(ao_app->get_casing_steno_enabled()); - ui_blank_blips_cb = new QCheckBox(ui_audio_widget); - ui_blank_blips_cb->setChecked(p_ao_app->get_blank_blip()); + ui_casing_layout->setWidget(6, QFormLayout::FieldRole, ui_casing_steno_cb); - ui_audio_layout->setWidget(7, QFormLayout::FieldRole, ui_blank_blips_cb); + // -- CM ANNOUNCEMENTS - ui_loopsfx_lbl = new QLabel(ui_audio_widget); - ui_loopsfx_lbl->setText(tr("Enable Looping SFX:")); - ui_loopsfx_lbl->setToolTip(tr("If true, the game will allow looping sound effects to play on preanimations.")); + ui_casing_cm_lbl = new QLabel(ui_casing_widget); + ui_casing_cm_lbl->setText(tr("CM:")); + ui_casing_cm_lbl->setToolTip( + tr("If checked, you will appear amongst the potential " + "CMs on the server.")); - ui_audio_layout->setWidget(8, QFormLayout::LabelRole, ui_loopsfx_lbl); + ui_casing_layout->setWidget(7, QFormLayout::LabelRole, ui_casing_cm_lbl); - ui_loopsfx_cb = new QCheckBox(ui_audio_widget); - ui_loopsfx_cb->setChecked(p_ao_app->get_looping_sfx()); + ui_casing_cm_cb = new QCheckBox(ui_casing_widget); + ui_casing_cm_cb->setChecked(ao_app->get_casing_cm_enabled()); - ui_audio_layout->setWidget(8, QFormLayout::FieldRole, ui_loopsfx_cb); + ui_casing_layout->setWidget(7, QFormLayout::FieldRole, ui_casing_cm_cb); + ui_casing_wit_lbl = new QLabel(ui_casing_widget); + ui_casing_wit_lbl->setText(tr("Witness:")); + ui_casing_wit_lbl->setToolTip( + tr("If checked, you will appear amongst the potential " + "witnesses on the server.")); - ui_objectmusic_lbl = new QLabel(ui_audio_widget); - ui_objectmusic_lbl->setText(tr("Kill Music On Objection:")); - ui_objectmusic_lbl->setToolTip(tr("If true, the game will stop music when someone objects, like in the actual games.")); + ui_casing_layout->setWidget(8, QFormLayout::LabelRole, ui_casing_wit_lbl); - ui_audio_layout->setWidget(9, QFormLayout::LabelRole, ui_objectmusic_lbl); + ui_casing_wit_cb = new QCheckBox(ui_casing_widget); + ui_casing_wit_cb->setChecked(ao_app->get_casing_wit_enabled()); - ui_objectmusic_cb = new QCheckBox(ui_audio_widget); - ui_objectmusic_cb->setChecked(p_ao_app->get_objectmusic()); + ui_casing_layout->setWidget(8, QFormLayout::FieldRole, ui_casing_wit_cb); - ui_audio_layout->setWidget(9, QFormLayout::FieldRole, ui_objectmusic_cb); + // -- CM CASES ANNOUNCEMENTS - // The casing tab! - ui_casing_tab = new QWidget(); - ui_settings_tabs->addTab(ui_casing_tab, tr("Casing")); + ui_casing_cm_cases_lbl = new QLabel(ui_casing_widget); + ui_casing_cm_cases_lbl->setText(tr("Hosting cases:")); + ui_casing_cm_cases_lbl->setToolTip( + tr("If you're a CM, enter what cases you are " + "willing to host.")); - ui_casing_widget = new QWidget(ui_casing_tab); - ui_casing_widget->setGeometry(QRect(10,10, 361, 211)); + ui_casing_layout->setWidget(9, QFormLayout::LabelRole, + ui_casing_cm_cases_lbl); - ui_casing_layout = new QFormLayout(ui_casing_widget); - ui_casing_layout->setLabelAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter); - ui_casing_layout->setFormAlignment(Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop); - ui_casing_layout->setContentsMargins(0, 0, 0, 0); + ui_casing_cm_cases_textbox = new QLineEdit(ui_casing_widget); + ui_casing_cm_cases_textbox->setText(ao_app->get_casing_can_host_cases()); - // -- SERVER SUPPORTS CASING + ui_casing_layout->setWidget(9, QFormLayout::FieldRole, + ui_casing_cm_cases_textbox); - ui_casing_supported_lbl = new QLabel(ui_casing_widget); - if (ao_app->casing_alerts_enabled) - ui_casing_supported_lbl->setText(tr("This server supports case alerts.")); - else - ui_casing_supported_lbl->setText(tr("This server does not support case alerts.")); - ui_casing_supported_lbl->setToolTip(tr("Pretty self-explanatory.")); + // ICLOG - ui_casing_layout->setWidget(0, QFormLayout::FieldRole, ui_casing_supported_lbl); + ui_other_tab = new QWidget(); + ui_settings_tabs->addTab(ui_other_tab, tr("IC_Log")); - // -- CASE ANNOUNCEMENTS + ui_other_widget = new QWidget(ui_other_tab); + ui_other_widget->setGeometry(QRect(10, 10, 361, 211)); - ui_casing_enabled_lbl = new QLabel(ui_casing_widget); - ui_casing_enabled_lbl->setText(tr("Casing:")); - ui_casing_enabled_lbl->setToolTip(tr("If checked, you will get alerts about case " - "announcements.")); + ui_other_layout = new QFormLayout(ui_other_widget); + ui_other_layout->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignVCenter); + ui_other_layout->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft | + Qt::AlignTop); + ui_other_layout->setContentsMargins(0, 0, 0, 0); - ui_casing_layout->setWidget(1, QFormLayout::LabelRole, ui_casing_enabled_lbl); + ui_other_fancy_icl_enabled_lb = new QLabel(ui_other_widget); + ui_other_fancy_icl_enabled_lb->setText(tr("Colorful IC log:")); + ui_other_fancy_icl_enabled_lb->setToolTip( + tr("Enables colored text in the log.")); + ui_other_layout->setWidget(1, QFormLayout::LabelRole, + ui_other_fancy_icl_enabled_lb); - ui_casing_enabled_cb = new QCheckBox(ui_casing_widget); - ui_casing_enabled_cb->setChecked(ao_app->get_casing_enabled()); + ui_other_fancy_icl_enabled_cb = new QCheckBox(ui_other_widget); + ui_other_fancy_icl_enabled_cb->setChecked( + ao_app->get_colored_iclog_enabled()); + ui_other_layout->setWidget(1, QFormLayout::FieldRole, + ui_other_fancy_icl_enabled_cb); - ui_casing_layout->setWidget(1, QFormLayout::FieldRole, ui_casing_enabled_cb); + ui_other_fancy_icl_limit_lb = new QLabel(ui_other_widget); + ui_other_fancy_icl_limit_lb->setText(tr("Only inline coloring:")); + ui_other_fancy_icl_limit_lb->setToolTip( + tr("Only inline coloring will be shown such as <>,|| etc")); + ui_other_layout->setWidget(2, QFormLayout::LabelRole, + ui_other_fancy_icl_limit_lb); + ui_other_fancy_icl_limit_cb = new QCheckBox(ui_other_widget); + ui_other_fancy_icl_limit_cb->setChecked( + ao_app->colorlog_restricted_enabled()); + ui_other_layout->setWidget(2, QFormLayout::FieldRole, + ui_other_fancy_icl_limit_cb); - // -- DEFENSE ANNOUNCEMENTS - - ui_casing_def_lbl = new QLabel(ui_casing_widget); - ui_casing_def_lbl->setText(tr("Defense:")); - ui_casing_def_lbl->setToolTip(tr("If checked, you will get alerts about case " - "announcements if a defense spot is open.")); - - ui_casing_layout->setWidget(2, QFormLayout::LabelRole, ui_casing_def_lbl); - - ui_casing_def_cb = new QCheckBox(ui_casing_widget); - ui_casing_def_cb->setChecked(ao_app->get_casing_defence_enabled()); - - ui_casing_layout->setWidget(2, QFormLayout::FieldRole, ui_casing_def_cb); - - // -- PROSECUTOR ANNOUNCEMENTS - - ui_casing_pro_lbl = new QLabel(ui_casing_widget); - ui_casing_pro_lbl->setText(tr("Prosecution:")); - ui_casing_pro_lbl->setToolTip(tr("If checked, you will get alerts about case " - "announcements if a prosecutor spot is open.")); - - ui_casing_layout->setWidget(3, QFormLayout::LabelRole, ui_casing_pro_lbl); - - ui_casing_pro_cb = new QCheckBox(ui_casing_widget); - ui_casing_pro_cb->setChecked(ao_app->get_casing_prosecution_enabled()); - - ui_casing_layout->setWidget(3, QFormLayout::FieldRole, ui_casing_pro_cb); - - // -- JUDGE ANNOUNCEMENTS - - ui_casing_jud_lbl = new QLabel(ui_casing_widget); - ui_casing_jud_lbl->setText(tr("Judge:")); - ui_casing_jud_lbl->setToolTip(tr("If checked, you will get alerts about case " - "announcements if the judge spot is open.")); - - ui_casing_layout->setWidget(4, QFormLayout::LabelRole, ui_casing_jud_lbl); - - ui_casing_jud_cb = new QCheckBox(ui_casing_widget); - ui_casing_jud_cb->setChecked(ao_app->get_casing_judge_enabled()); - - ui_casing_layout->setWidget(4, QFormLayout::FieldRole, ui_casing_jud_cb); - - // -- JUROR ANNOUNCEMENTS - - ui_casing_jur_lbl = new QLabel(ui_casing_widget); - ui_casing_jur_lbl->setText(tr("Juror:")); - ui_casing_jur_lbl->setToolTip(tr("If checked, you will get alerts about case " - "announcements if a juror spot is open.")); - - ui_casing_layout->setWidget(5, QFormLayout::LabelRole, ui_casing_jur_lbl); - - ui_casing_jur_cb = new QCheckBox(ui_casing_widget); - ui_casing_jur_cb->setChecked(ao_app->get_casing_juror_enabled()); - - ui_casing_layout->setWidget(5, QFormLayout::FieldRole, ui_casing_jur_cb); - - // -- STENO ANNOUNCEMENTS - - ui_casing_steno_lbl = new QLabel(ui_casing_widget); - ui_casing_steno_lbl->setText(tr("Stenographer:")); - ui_casing_steno_lbl->setToolTip(tr("If checked, you will get alerts about case " - "announcements if a stenographer spot is open.")); - - ui_casing_layout->setWidget(6, QFormLayout::LabelRole, ui_casing_steno_lbl); - - ui_casing_steno_cb = new QCheckBox(ui_casing_widget); - ui_casing_steno_cb->setChecked(ao_app->get_casing_steno_enabled()); - - ui_casing_layout->setWidget(6, QFormLayout::FieldRole, ui_casing_steno_cb); - - // -- CM ANNOUNCEMENTS - - ui_casing_cm_lbl = new QLabel(ui_casing_widget); - ui_casing_cm_lbl->setText(tr("CM:")); - ui_casing_cm_lbl->setToolTip(tr("If checked, you will appear amongst the potential " - "CMs on the server.")); - - ui_casing_layout->setWidget(7, QFormLayout::LabelRole, ui_casing_cm_lbl); - - ui_casing_cm_cb = new QCheckBox(ui_casing_widget); - ui_casing_cm_cb->setChecked(ao_app->get_casing_cm_enabled()); - - ui_casing_layout->setWidget(7, QFormLayout::FieldRole, ui_casing_cm_cb); - - ui_casing_wit_lbl = new QLabel(ui_casing_widget); - ui_casing_wit_lbl->setText(tr("Witness:")); - ui_casing_wit_lbl->setToolTip(tr("If checked, you will appear amongst the potential " - "witnesses on the server.")); - - ui_casing_layout->setWidget(8, QFormLayout::LabelRole, ui_casing_wit_lbl); - - ui_casing_wit_cb = new QCheckBox(ui_casing_widget); - ui_casing_wit_cb->setChecked(ao_app->get_casing_wit_enabled()); - - ui_casing_layout->setWidget(8, QFormLayout::FieldRole, ui_casing_wit_cb); - - // -- CM CASES ANNOUNCEMENTS - - ui_casing_cm_cases_lbl = new QLabel(ui_casing_widget); - ui_casing_cm_cases_lbl->setText(tr("Hosting cases:")); - ui_casing_cm_cases_lbl->setToolTip(tr("If you're a CM, enter what cases you are " - "willing to host.")); - - ui_casing_layout->setWidget(9, QFormLayout::LabelRole, ui_casing_cm_cases_lbl); - - ui_casing_cm_cases_textbox = new QLineEdit(ui_casing_widget); - ui_casing_cm_cases_textbox->setText(ao_app->get_casing_can_host_cases()); - - ui_casing_layout->setWidget(9, QFormLayout::FieldRole, ui_casing_cm_cases_textbox); - - // When we're done, we should continue the updates! - setUpdatesEnabled(true); + ui_other_mirror_icl_enabled_lb = new QLabel(ui_other_widget); + ui_other_mirror_icl_enabled_lb->setText(tr("Mirror IC log:")); + ui_other_mirror_icl_enabled_lb->setToolTip( + tr("IC log will mirror the IC box. " + "Meaning that if somebody gets interupted nobody will know what they " + "wanted to say. " + "Enable for a more realistic expierence")); + ui_other_layout->setWidget(3, QFormLayout::LabelRole, + ui_other_mirror_icl_enabled_lb); + ui_other_mirror_icl_enabled_cb = new QCheckBox(ui_other_widget); + ui_other_mirror_icl_enabled_cb->setChecked(ao_app->get_iclmir_enabled()); + ui_other_layout->setWidget(3, QFormLayout::FieldRole, + ui_other_mirror_icl_enabled_cb); + + ui_downwards_lbl = new QLabel(ui_other_widget); + ui_downwards_lbl->setText(tr("Log goes downwards:")); + ui_downwards_lbl->setToolTip( + tr("If ticked, new messages will appear at " + "the bottom (like the OOC chatlog). The traditional " + "(AO1) behaviour is equivalent to this being unticked.")); + + ui_other_layout->setWidget(4, QFormLayout::LabelRole, ui_downwards_lbl); + + ui_downwards_cb = new QCheckBox(ui_other_widget); + ui_downwards_cb->setChecked(p_ao_app->get_log_goes_downwards()); + + ui_other_layout->setWidget(4, QFormLayout::FieldRole, ui_downwards_cb); + + ui_length_lbl = new QLabel(ui_other_widget); + ui_length_lbl->setText(tr("Log length:")); + ui_length_lbl->setToolTip(tr( + "The amount of messages the IC chatlog will keep before " + "deleting older messages. A value of 0 or below counts as 'infinite'.")); + + ui_other_layout->setWidget(5, QFormLayout::LabelRole, ui_length_lbl); + + ui_length_spinbox = new QSpinBox(ui_other_widget); + ui_length_spinbox->setMaximum(10000); + ui_length_spinbox->setValue(p_ao_app->get_max_log_size()); + + ui_other_layout->setWidget(5, QFormLayout::FieldRole, ui_length_spinbox); + + // When we're done, we should continue the updates! + setUpdatesEnabled(true); } void AOOptionsDialog::save_pressed() { - // Save everything into the config.ini. - QSettings* configini = ao_app->configini; + // Save everything into the config.ini. + QSettings *configini = ao_app->configini; - configini->setValue("theme", ui_theme_combobox->currentText()); - configini->setValue("log_goes_downwards", ui_downwards_cb->isChecked()); - configini->setValue("log_maximum", ui_length_spinbox->value()); - configini->setValue("default_username", ui_username_textbox->text()); - configini->setValue("show_custom_shownames", ui_showname_cb->isChecked()); - configini->setValue("master", ui_ms_textbox->text()); - configini->setValue("discord", ui_discord_cb->isChecked()); - configini->setValue("shakeandflash", ui_epilepsy_cb->isChecked()); - configini->setValue("language", ui_language_combobox->currentText().left(2)); - - QFile* callwordsini = new QFile(ao_app->get_base_path() + "callwords.ini"); - - if (!callwordsini->open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) - { - // Nevermind! - } - else - { - QTextStream out(callwordsini); - out << ui_callwords_textbox->toPlainText(); - callwordsini->close(); - } - - configini->setValue("default_audio_device", ui_audio_device_combobox->currentText()); - configini->setValue("default_music", ui_music_volume_spinbox->value()); - configini->setValue("default_sfx", ui_sfx_volume_spinbox->value()); - configini->setValue("default_blip", ui_blips_volume_spinbox->value()); - configini->setValue("blip_rate", ui_bliprate_spinbox->value()); - configini->setValue("blank_blip", ui_blank_blips_cb->isChecked()); - configini->setValue("looping_sfx", ui_loopsfx_cb->isChecked()); - configini->setValue("kill_music_on_object", ui_objectmusic_cb->isChecked()); - - configini->setValue("casing_enabled", ui_casing_enabled_cb->isChecked()); - configini->setValue("casing_defence_enabled", ui_casing_def_cb->isChecked()); - configini->setValue("casing_prosecution_enabled", ui_casing_pro_cb->isChecked()); - configini->setValue("casing_judge_enabled", ui_casing_jud_cb->isChecked()); - configini->setValue("casing_juror_enabled", ui_casing_jur_cb->isChecked()); - configini->setValue("casing_steno_enabled", ui_casing_steno_cb->isChecked()); - configini->setValue("casing_cm_enabled", ui_casing_cm_cb->isChecked()); - configini->setValue("casing_wit_enabled", ui_casing_wit_cb->isChecked()); - configini->setValue("casing_can_host_cases", ui_casing_cm_cases_textbox->text()); + configini->setValue("theme", ui_theme_combobox->currentText()); + configini->setValue("log_goes_downwards", ui_downwards_cb->isChecked()); + configini->setValue("log_maximum", ui_length_spinbox->value()); + configini->setValue("default_username", ui_username_textbox->text()); + configini->setValue("show_custom_shownames", ui_showname_cb->isChecked()); + configini->setValue("master", ui_ms_textbox->text()); + configini->setValue("discord", ui_discord_cb->isChecked()); + configini->setValue("shakeandflash", ui_epilepsy_cb->isChecked()); + configini->setValue("language", ui_language_combobox->currentText().left(2)); + configini->setValue("punctuation_delay", ui_pun_delay_spinbox->value()); + configini->setValue("keep_evidence", ui_keepevi_cb->isChecked()); + QFile *callwordsini = new QFile(ao_app->get_base_path() + "callwords.ini"); + if (!callwordsini->open(QIODevice::WriteOnly | QIODevice::Truncate | + QIODevice::Text)) { + // Nevermind! + } + else { + QTextStream out(callwordsini); + out << ui_callwords_textbox->toPlainText(); callwordsini->close(); - done(0); + } + + configini->setValue("default_audio_device", + ui_audio_device_combobox->currentText()); + configini->setValue("default_music", ui_music_volume_spinbox->value()); + configini->setValue("default_sfx", ui_sfx_volume_spinbox->value()); + configini->setValue("default_blip", ui_blips_volume_spinbox->value()); + configini->setValue("blip_rate", ui_bliprate_spinbox->value()); + configini->setValue("blank_blip", ui_blank_blips_cb->isChecked()); + configini->setValue("looping_sfx", ui_loopsfx_cb->isChecked()); + configini->setValue("kill_music_on_object", ui_objectmusic_cb->isChecked()); + + configini->setValue("casing_enabled", ui_casing_enabled_cb->isChecked()); + configini->setValue("casing_defence_enabled", ui_casing_def_cb->isChecked()); + configini->setValue("casing_prosecution_enabled", + ui_casing_pro_cb->isChecked()); + configini->setValue("casing_judge_enabled", ui_casing_jud_cb->isChecked()); + configini->setValue("casing_juror_enabled", ui_casing_jur_cb->isChecked()); + configini->setValue("casing_steno_enabled", ui_casing_steno_cb->isChecked()); + configini->setValue("casing_cm_enabled", ui_casing_cm_cb->isChecked()); + configini->setValue("casing_wit_enabled", ui_casing_wit_cb->isChecked()); + configini->setValue("casing_can_host_cases", + ui_casing_cm_cases_textbox->text()); + + configini->setValue("color_iclog_enabled", + ui_other_fancy_icl_enabled_cb->isChecked()); + configini->setValue("mirror_iclog_enabled", + ui_other_mirror_icl_enabled_cb->isChecked()); + configini->setValue("mirror_iclog_restricted", + ui_other_fancy_icl_limit_cb->isChecked()); + + callwordsini->close(); + done(0); } -void AOOptionsDialog::discard_pressed() -{ - done(0); -} +void AOOptionsDialog::discard_pressed() { done(0); } -#if (defined (_WIN32) || defined (_WIN64)) -bool AOOptionsDialog::needs_default_audiodev() -{ - return true; -} -#elif (defined (LINUX) || defined (__linux__)) -bool AOOptionsDialog::needs_default_audiodev() -{ - return false; -} +#if (defined(_WIN32) || defined(_WIN64)) +bool AOOptionsDialog::needs_default_audiodev() { return true; } +#elif (defined(LINUX) || defined(__linux__)) +bool AOOptionsDialog::needs_default_audiodev() { return false; } #elif defined __APPLE__ -bool AOOptionsDialog::needs_default_audiodev() -{ - return true; -} +bool AOOptionsDialog::needs_default_audiodev() { return true; } #else #error This operating system is not supported. #endif diff --git a/src/aoscene.cpp b/src/aoscene.cpp index 344522b..fc68633 100644 --- a/src/aoscene.cpp +++ b/src/aoscene.cpp @@ -7,16 +7,19 @@ AOScene::AOScene(QWidget *parent, AOApplication *p_ao_app) : QLabel(parent) m_parent = parent; ao_app = p_ao_app; m_movie = new QMovie(this); + last_image = ""; } void AOScene::set_image(QString p_image) { - QString background_path = ao_app->get_background_path(p_image + ".png"); - QString animated_background_path = ao_app->get_background_path(p_image + ".gif"); - QString default_path = ao_app->get_default_background_path(p_image + ".png"); + QString background_path = + ao_app->get_image_suffix(ao_app->get_background_path(p_image)); + if (!file_exists(background_path)) + background_path = ao_app->get_image_suffix( + ao_app->get_default_background_path(p_image)); // Default path - QPixmap background(background_path); - QPixmap default_bg(default_path); + if (file_exists(background_path) && background_path == last_image) + return; int w = this->width(); int h = this->height(); @@ -25,52 +28,58 @@ void AOScene::set_image(QString p_image) this->setMovie(nullptr); m_movie->stop(); - m_movie->setFileName(animated_background_path); + m_movie->setFileName(background_path); m_movie->setScaledSize(QSize(w, h)); - if (m_movie->isValid()) - { + if (m_movie->isValid()) { this->setMovie(m_movie); m_movie->start(); } - else if (file_exists(background_path)) - { + else { + QPixmap background(background_path); this->setPixmap(background.scaled(w, h)); } - else - { - this->setPixmap(default_bg.scaled(w, h)); - } + last_image = background_path; } void AOScene::set_legacy_desk(QString p_image) { - //vanilla desks vary in both width and height. in order to make that work with viewport rescaling, - //some INTENSE math is needed. - QString desk_path = ao_app->get_background_path(p_image); - QString default_path = ao_app->get_default_background_path(p_image); + QString desk_path = + ao_app->get_image_suffix(ao_app->get_background_path(p_image)); + if (!file_exists(desk_path)) + desk_path = ao_app->get_image_suffix( + ao_app->get_default_background_path(p_image)); // Default path - QPixmap f_desk; + if (file_exists(desk_path) && desk_path == last_image) + return; + QPixmap f_desk(desk_path); - if (file_exists(desk_path)) - f_desk.load(desk_path); - else - f_desk.load(default_path); + // vanilla desks vary in both width and height. in order to make that work + // with viewport rescaling, some INTENSE math is needed. int vp_width = m_parent->width(); int vp_height = m_parent->height(); - //double y_modifier = 147 / 192; - //double w_modifier = vp_width / 256; double h_modifier = vp_height / 192; - //int final_y = y_modifier * vp_height; - //int final_w = w_modifier * f_desk.width(); int final_h = static_cast(h_modifier * f_desk.height()); - //this->resize(final_w, final_h); - //this->setPixmap(f_desk.scaled(final_w, final_h)); - this->resize(vp_width, final_h); - this->setPixmap(f_desk.scaled(vp_width, final_h)); + this->clear(); + this->setMovie(nullptr); + + m_movie->stop(); + m_movie->setFileName(desk_path); + + m_movie->setScaledSize(QSize(vp_width, final_h)); + + if (m_movie->isValid()) { + this->setMovie(m_movie); + m_movie->start(); + } + else { + this->resize(vp_width, final_h); + this->setPixmap(f_desk.scaled(vp_width, final_h)); + } + last_image = desk_path; } diff --git a/src/aotextarea.cpp b/src/aotextarea.cpp index 5e14632..c741569 100644 --- a/src/aotextarea.cpp +++ b/src/aotextarea.cpp @@ -5,7 +5,8 @@ AOTextArea::AOTextArea(QWidget *p_parent) : QTextBrowser(p_parent) } -void AOTextArea::append_chatmessage(QString p_name, QString p_message, QString p_colour) +void AOTextArea::append_chatmessage(QString p_name, QString p_message, + QString p_colour, bool song) { const QTextCursor old_cursor = this->textCursor(); const int old_scrollbar_value = this->verticalScrollBar()->value(); @@ -14,7 +15,12 @@ void AOTextArea::append_chatmessage(QString p_name, QString p_message, QString p this->moveCursor(QTextCursor::End); this->append(""); - this->insertHtml("" + p_name.toHtmlEscaped() + ": "); + if (song) + this->insertHtml("" + + p_name.toHtmlEscaped() + " "); + else + this->insertHtml("" + + p_name.toHtmlEscaped() + ": "); //cheap workarounds ahoy p_message += " "; diff --git a/src/charselect.cpp b/src/charselect.cpp index d6ee044..e942fbe 100644 --- a/src/charselect.cpp +++ b/src/charselect.cpp @@ -8,55 +8,51 @@ class AOCharSelectGenerationThreading : public QRunnable { public: - Courtroom *thisCourtroom; - int char_num; - AOCharButton *char_button; - AOCharSelectGenerationThreading(Courtroom *my_courtroom, int character_number, AOCharButton *charbut){ - thisCourtroom = my_courtroom; - char_num = character_number; - char_button = charbut; - } - void run() - { - AOCharButton* thisCharacterButton = char_button; - thisCharacterButton->reset(); - thisCharacterButton->hide(); - thisCharacterButton->set_image(thisCourtroom->char_list.at(char_num).name); - thisCourtroom->ui_char_button_list.append(thisCharacterButton); + Courtroom *thisCourtroom; + int char_num; + AOCharButton *char_button; + AOCharSelectGenerationThreading(Courtroom *my_courtroom, int character_number) + { + thisCourtroom = my_courtroom; + char_num = character_number; + } + void run() + { + // we take the button we are supposed to mess with, and not whatever comes + // first + AOCharButton *thisCharacterButton = + thisCourtroom->ui_char_button_list.at(char_num); + thisCharacterButton->reset(); + thisCharacterButton->hide(); + thisCharacterButton->set_image(thisCourtroom->char_list.at(char_num).name); - thisCourtroom->connect(thisCharacterButton, SIGNAL(clicked()), thisCourtroom->char_button_mapper, SLOT(map())); - thisCourtroom->char_button_mapper->setMapping(thisCharacterButton, thisCourtroom->ui_char_button_list.size() - 1); - } + thisCourtroom->connect(thisCharacterButton, SIGNAL(clicked()), + thisCourtroom->char_button_mapper, SLOT(map())); + thisCourtroom->char_button_mapper->setMapping(thisCharacterButton, + char_num); + } }; -class AOCharSelectFilterThreading : public QRunnable +void AOCharSelectFilter(Courtroom *thisCourtroom, int char_num) { -public: - Courtroom *thisCourtroom; - int char_num; - AOCharSelectFilterThreading(Courtroom *my_courtroom, int character_number){ - thisCourtroom = my_courtroom; - char_num = character_number; - } - void run() - { - AOCharButton* current_char = thisCourtroom->ui_char_button_list.at(char_num); + AOCharButton *current_char = thisCourtroom->ui_char_button_list.at(char_num); - if (!thisCourtroom->ui_char_taken->isChecked() && thisCourtroom->char_list.at(char_num).taken) - return; + if (!thisCourtroom->ui_char_taken->isChecked() && + thisCourtroom->char_list.at(char_num).taken) + return; - if (!thisCourtroom->char_list.at(char_num).name.contains(thisCourtroom->ui_char_search->text(), Qt::CaseInsensitive)) - return; + if (!thisCourtroom->char_list.at(char_num).name.contains( + thisCourtroom->ui_char_search->text(), Qt::CaseInsensitive)) + return; - // We only really need to update the fact that a character is taken - // for the buttons that actually appear. - // You'd also update the passwordedness and etc. here later. - current_char->reset(); - current_char->set_taken(thisCourtroom->char_list.at(char_num).taken); + // We only really need to update the fact that a character is taken + // for the buttons that actually appear. + // You'd also update the passwordedness and etc. here later. + current_char->reset(); + current_char->set_taken(thisCourtroom->char_list.at(char_num).taken); - thisCourtroom->ui_char_button_list_filtered.append(current_char); - } -}; + thisCourtroom->ui_char_button_list_filtered.append(current_char); +} void Courtroom::construct_char_select() { @@ -246,39 +242,40 @@ void Courtroom::character_loading_finished() ui_char_button_list.clear(); } - // First, we'll make all the character buttons in the very beginning. - // We also hide them all, so they can't be accidentally clicked. - // Later on, we'll be revealing buttons as we need them. - for (int n = 0; n < char_list.size(); n++) - { - AOCharButton* characterButton = new AOCharButton(ui_char_buttons, ao_app, 0, 0, char_list.at(n).taken); - AOCharSelectGenerationThreading *char_generate = new AOCharSelectGenerationThreading(this, n, characterButton); - QThreadPool::globalInstance()->start(char_generate); - if(QThreadPool::globalInstance()->activeThreadCount() == QThreadPool::globalInstance()->maxThreadCount()) - { - QThreadPool::globalInstance()->waitForDone(); - } + // First, we'll make all the character buttons in the very beginning. + // Since we can't trust what will happen during the multi threading process, + // we assign the buttons their locations in the list according to the + // character list. + for (int n = 0; n < char_list.size(); n++) { + AOCharButton *characterButton = + new AOCharButton(ui_char_buttons, ao_app, 0, 0, char_list.at(n).taken); + ui_char_button_list.append(characterButton); + } + + // We also hide them all, so they can't be accidentally clicked. + // Later on, we'll be revealing buttons as we need them. + for (int n = 0; n < char_list.size(); n++) { + AOCharSelectGenerationThreading *char_generate = + new AOCharSelectGenerationThreading(this, n); + QThreadPool::globalInstance()->start(char_generate); + if (QThreadPool::globalInstance()->activeThreadCount() == + QThreadPool::globalInstance()->maxThreadCount()) { + QThreadPool::globalInstance()->waitForDone(); } - QThreadPool::globalInstance()->waitForDone(); - filter_character_list(); + } + QThreadPool::globalInstance()->waitForDone(); + filter_character_list(); } void Courtroom::filter_character_list() { - ui_char_button_list_filtered.clear(); - for (int i = 0; i < char_list.size(); i++) - { - AOCharSelectFilterThreading *char_filter = new AOCharSelectFilterThreading(this, i); - QThreadPool::globalInstance()->start(char_filter); - if(QThreadPool::globalInstance()->activeThreadCount() == QThreadPool::globalInstance()->maxThreadCount()) - { - QThreadPool::globalInstance()->waitForDone(); - } - } - QThreadPool::globalInstance()->waitForDone(); + ui_char_button_list_filtered.clear(); + for (int i = 0; i < char_list.size(); i++) { + AOCharSelectFilter(this, i); + } - current_char_page = 0; - set_char_select_page(); + current_char_page = 0; + set_char_select_page(); } void Courtroom::on_char_search_changed() diff --git a/src/chatlogpiece.cpp b/src/chatlogpiece.cpp index 6c861f0..b96d502 100644 --- a/src/chatlogpiece.cpp +++ b/src/chatlogpiece.cpp @@ -5,25 +5,31 @@ chatlogpiece::chatlogpiece() name = "UNKNOWN"; showname = "UNKNOWN"; message = "UNKNOWN"; + color = 0; is_song = false; datetime = QDateTime::currentDateTime().toUTC(); } -chatlogpiece::chatlogpiece(QString p_name, QString p_showname, QString p_message, bool p_song) +chatlogpiece::chatlogpiece(QString p_name, QString p_showname, + QString p_message, bool p_song, int p_color) { name = p_name; showname = p_showname; message = p_message; is_song = p_song; + color = p_color; datetime = QDateTime::currentDateTime().toUTC(); } -chatlogpiece::chatlogpiece(QString p_name, QString p_showname, QString p_message, bool p_song, QDateTime p_datetime) +chatlogpiece::chatlogpiece(QString p_name, QString p_showname, + QString p_message, bool p_song, int p_color, + QDateTime p_datetime) { name = p_name; showname = p_showname; message = p_message; is_song = p_song; + color = p_color; datetime = p_datetime.toUTC(); } @@ -57,6 +63,7 @@ QString chatlogpiece::get_datetime_as_string() return datetime.toString(); } +int chatlogpiece::get_chat_color() { return color; } QString chatlogpiece::get_full() { diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 6e5397e..71910ab 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -57,12 +57,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() realization_timer = new QTimer(this); realization_timer->setSingleShot(true); - testimony_show_timer = new QTimer(this); - testimony_show_timer->setSingleShot(true); - - testimony_hide_timer = new QTimer(this); - testimony_hide_timer->setSingleShot(true); - char_button_mapper = new QSignalMapper(this); music_player = new AOMusicPlayer(this, ao_app); @@ -78,9 +72,11 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() misc_sfx_player->set_volume(0); frame_emote_sfx_player = new AOSfxPlayer(this, ao_app); frame_emote_sfx_player->set_volume(0); - pair_frame_emote_sfx_player = new AOSfxPlayer(this, ao_app); // todo: recode pair + pair_frame_emote_sfx_player = new AOSfxPlayer(this, ao_app); pair_frame_emote_sfx_player->set_volume(0); + char_button_mapper = new QSignalMapper(this); + blip_player = new AOBlipPlayer(this, ao_app); blip_player->set_volume(0); @@ -113,8 +109,9 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_vp_message->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ui_vp_message->setReadOnly(true); - ui_vp_testimony = new AOImage(this, ao_app); - ui_vp_realization = new AOImage(this, ao_app); + ui_vp_testimony = new AOMovie(this, ao_app); + ui_vp_testimony->set_play_once(false); + ui_vp_realization = new AOMovie(this, ao_app); ui_vp_wtce = new AOMovie(this, ao_app); ui_vp_objection = new AOMovie(this, ao_app); @@ -134,8 +131,20 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_server_chatlog->setOpenExternalLinks(true); ui_area_list = new QListWidget(this); - ui_area_list->hide(); - ui_music_list = new QListWidget(this); + + ui_music_list = new QTreeWidget(this); + ui_music_list->setColumnCount(2); + ui_music_list->hideColumn(1); + ui_music_list->setHeaderHidden(true); + ui_music_list->setContextMenuPolicy(Qt::CustomContextMenu); + ui_music_list->setAutoFillBackground(true); + ui_music_list->setExpandsOnDoubleClick(true); + ui_music_list->setRootIsDecorated(true); + ui_music_list->header()->setStretchLastSection(false); + ui_music_list->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + ui_music_list->setContextMenuPolicy(Qt::CustomContextMenu); + + ui_music_list->hide(); ui_ic_chat_name = new QLineEdit(this); ui_ic_chat_name->setFrame(false); @@ -158,6 +167,12 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_ooc_chat_name->setMaxLength(30); ui_ooc_chat_name->setText(p_ao_app->get_default_username()); + punctuation_modifier = p_ao_app->get_pundelay(); + colorf_iclog = p_ao_app->get_colored_iclog_enabled(); + mirror_iclog = p_ao_app->get_iclmir_enabled(); + colorf_limit = p_ao_app->colorlog_restricted_enabled(); + keep_evidence_display = p_ao_app->is_keepevi_enabled(); + //ui_area_password = new QLineEdit(this); //ui_area_password->setFrame(false); ui_music_search = new QLineEdit(this); @@ -233,6 +248,9 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_pre_non_interrupt->hide(); ui_custom_objection = new AOButton(this, ao_app); + ui_custom_objection->setContextMenuPolicy(Qt::CustomContextMenu); + custom_obj_menu = new QMenu; + ui_realization = new AOButton(this, ao_app); ui_screenshake = new AOButton(this, ao_app); ui_mute = new AOButton(this, ao_app); @@ -296,31 +314,34 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() connect(realization_timer, SIGNAL(timeout()), this, SLOT(realization_done())); - connect(testimony_show_timer, SIGNAL(timeout()), this, SLOT(hide_testimony())); - connect(testimony_hide_timer, SIGNAL(timeout()), this, SLOT(show_testimony())); connect(ui_emote_left, SIGNAL(clicked()), this, SLOT(on_emote_left_clicked())); connect(ui_emote_right, SIGNAL(clicked()), this, SLOT(on_emote_right_clicked())); connect(ui_emote_dropdown, SIGNAL(activated(int)), this, SLOT(on_emote_dropdown_changed(int))); connect(ui_pos_dropdown, SIGNAL(currentIndexChanged(int)), this, SLOT(on_pos_dropdown_changed(int))); + connect(ui_mute_list, SIGNAL(clicked(QModelIndex)), this, + SLOT(on_mute_list_clicked(QModelIndex))); - connect(ui_mute_list, SIGNAL(clicked(QModelIndex)), this, SLOT(on_mute_list_clicked(QModelIndex))); connect(ui_ic_chat_message, SIGNAL(returnPressed()), this, SLOT(on_chat_return_pressed())); connect(ui_ooc_chat_message, SIGNAL(returnPressed()), this, SLOT(on_ooc_return_pressed())); - - connect(ui_music_list, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_music_list_double_clicked(QModelIndex))); - connect(ui_area_list, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(on_area_list_double_clicked(QModelIndex))); - + connect(ui_music_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), + this, SLOT(on_music_list_double_clicked(QTreeWidgetItem *, int))); + connect(ui_area_list, SIGNAL(doubleClicked(QModelIndex)), this, + SLOT(on_area_list_double_clicked(QModelIndex))); connect(ui_hold_it, SIGNAL(clicked()), this, SLOT(on_hold_it_clicked())); connect(ui_objection, SIGNAL(clicked()), this, SLOT(on_objection_clicked())); connect(ui_take_that, SIGNAL(clicked()), this, SLOT(on_take_that_clicked())); - connect(ui_custom_objection, SIGNAL(clicked()), this, SLOT(on_custom_objection_clicked())); connect(ui_realization, SIGNAL(clicked()), this, SLOT(on_realization_clicked())); connect(ui_screenshake, SIGNAL(clicked()), this, SLOT(on_screenshake_clicked())); + connect(ui_custom_objection, SIGNAL(clicked()), this, + SLOT(on_custom_objection_clicked())); + connect(ui_custom_objection, + SIGNAL(customContextMenuRequested(const QPoint &)), this, + SLOT(ShowContextMenu(const QPoint &))); connect(ui_mute, SIGNAL(clicked()), this, SLOT(on_mute_clicked())); connect(ui_defense_minus, SIGNAL(clicked()), this, SLOT(on_defense_minus_clicked())); @@ -509,14 +530,10 @@ void Courtroom::set_widgets() "color: white"); ui_vp_testimony->move(ui_viewport->x(), ui_viewport->y()); - ui_vp_testimony->resize(ui_viewport->width(), ui_viewport->height()); - ui_vp_testimony->set_image("testimony.png"); - ui_vp_testimony->hide(); + ui_vp_testimony->combo_resize(ui_viewport->width(), ui_viewport->height()); ui_vp_realization->move(ui_viewport->x(), ui_viewport->y()); - ui_vp_realization->resize(ui_viewport->width(), ui_viewport->height()); - ui_vp_realization->set_image("realizationflash.png"); - ui_vp_realization->hide(); + ui_vp_realization->combo_resize(ui_viewport->width(), ui_viewport->height()); ui_vp_wtce->move(ui_viewport->x(), ui_viewport->y()); ui_vp_wtce->combo_resize(ui_viewport->width(), ui_viewport->height()); @@ -543,6 +560,10 @@ void Courtroom::set_widgets() set_size_and_pos(ui_area_list, "music_list"); ui_area_list->setStyleSheet("background-color: rgba(0, 0, 0, 0);"); + ui_music_list->setStyleSheet("background-color: rgba(100, 103, 132, 225);"); + + ui_music_list->collapseAll(); + set_size_and_pos(ui_music_list, "music_list"); if (is_ao2_bg) @@ -802,7 +823,7 @@ void Courtroom::set_fonts() set_font(ui_ms_chatlog, "ms_chatlog"); set_font(ui_server_chatlog, "server_chatlog"); set_font(ui_music_list, "music_list"); - set_font(ui_area_list, "music_list"); + set_font(ui_area_list, "area_list"); // Set color of labels and checkboxes const QString design_file = "courtroom_fonts.ini"; @@ -918,7 +939,7 @@ void Courtroom::done_received() void Courtroom::set_background(QString p_background) { - testimony_in_progress = false; + ui_vp_testimony->stop(); current_background = p_background; @@ -1020,11 +1041,24 @@ void Courtroom::enter_courtroom(int p_cid) ui_prosecution_plus->hide(); } - if (ao_app->custom_objection_enabled && - (file_exists(ao_app->get_character_path(current_char, "custom.gif")) || - file_exists(ao_app->get_character_path(current_char, "custom.apng"))) && - file_exists(ao_app->get_character_path(current_char, "custom.wav"))) + if (ao_app->custom_objection_enabled && // if setting is enabled + (file_exists(ao_app->get_image_suffix( + ao_app->get_character_path(current_char, "custom"))) && + file_exists(ao_app->get_character_path(current_char, "custom.wav")))) { ui_custom_objection->show(); + if (dir_exists( + ao_app->get_character_path(current_char, "custom_objections"))) { + custom_obj_menu->clear(); + QDir directory( + ao_app->get_character_path(current_char, "custom_objections")); + QStringList custom_obj = directory.entryList(QStringList() << "*.gif" + << "*.apng", + QDir::Files); + for (const QString &filename : custom_obj) { + custom_obj_menu->addAction(filename); + } + } + } else ui_custom_objection->hide(); @@ -1049,7 +1083,11 @@ void Courtroom::enter_courtroom(int p_cid) pair_frame_emote_sfx_player->set_volume(ui_sfx_slider->value()); blip_player->set_volume(ui_blip_slider->value()); - testimony_in_progress = false; + misc_sfx_player->set_volume(ui_sfx_slider->value()); + frame_emote_sfx_player->set_volume(ui_sfx_slider->value()); + pair_frame_emote_sfx_player->set_volume(ui_sfx_slider->value()); + + ui_vp_testimony->stop(); set_widgets(); @@ -1064,7 +1102,6 @@ void Courtroom::enter_courtroom(int p_cid) void Courtroom::list_music() { ui_music_list->clear(); - music_row_to_number.clear(); QString f_file = "courtroom_design.ini"; @@ -1073,25 +1110,55 @@ void Courtroom::list_music() int n_listed_songs = 0; - for (int n_song = 0 ; n_song < music_list.size() ; ++n_song) - { + QTreeWidgetItem *parent = nullptr; + for (int n_song = 0; n_song < music_list.size(); ++n_song) { QString i_song = music_list.at(n_song); + QString i_song_listname = i_song.left(i_song.lastIndexOf(".")); + i_song_listname = i_song_listname.right( + i_song_listname.length() - (i_song_listname.lastIndexOf("/") + 1)); - if (i_song.toLower().contains(ui_music_search->text().toLower())) + QTreeWidgetItem *treeItem; + if (i_song_listname != i_song && parent != nullptr && + i_song.toLower().contains( + ui_music_search->text().toLower())) // not a category, parent exists { - ui_music_list->addItem(i_song); - music_row_to_number.append(n_song); + treeItem = new QTreeWidgetItem(parent); + treeItem->setText(0, i_song_listname); + treeItem->setText(1, i_song); + + QString song_path = ao_app->get_music_path(i_song); + + if (file_exists(song_path)) + treeItem->setBackground(0, found_brush); + else + treeItem->setBackground(0, missing_brush); + + if (i_song_listname == + i_song) // Not supposed to be a song to begin with - a category? + parent = treeItem; + ++n_listed_songs; + } + else if (i_song_listname == i_song) { + treeItem = new QTreeWidgetItem(ui_music_list); + treeItem->setText(0, i_song_listname); + treeItem->setText(1, i_song); QString song_path = ao_app->get_music_path(i_song); if (file_exists(song_path)) - ui_music_list->item(n_listed_songs)->setBackground(found_brush); + treeItem->setBackground(0, found_brush); else - ui_music_list->item(n_listed_songs)->setBackground(missing_brush); + treeItem->setBackground(0, missing_brush); + if (i_song_listname == + i_song) // Not supposed to be a song to begin with - a category? + parent = treeItem; ++n_listed_songs; } } + ui_music_list->expandAll(); // Needs to somehow remember which categories were + // expanded/collapsed if the music list didn't + // change since last time } void Courtroom::list_areas() @@ -1192,7 +1259,7 @@ void Courtroom::append_server_chatmessage(QString p_name, QString p_message, QSt append_server_chatmessage("CLIENT", tr("You were granted the Disable Modcalls button."), "1"); } - ui_server_chatlog->append_chatmessage(p_name, p_message, colour); + ui_server_chatlog->append_chatmessage(p_name, p_message, colour, false); } void Courtroom::detect_fallback_text() @@ -1344,11 +1411,9 @@ void Courtroom::on_chat_return_pressed() int f_emote_mod = ao_app->get_emote_mod(current_char, current_emote); //needed or else legacy won't understand what we're saying - if (objection_state > 0) - { - if (ui_pre->isChecked()) - { - if (f_emote_mod == 5) + if (objection_state > 0) { + if (ui_pre->isChecked()) { + if (f_emote_mod == 5 || f_emote_mod == 4) f_emote_mod = 6; else f_emote_mod = 2; @@ -1379,6 +1444,11 @@ void Courtroom::on_chat_return_pressed() if ((objection_state == 4 && !ao_app->custom_objection_enabled) || (objection_state < 0)) f_obj_state = "0"; + else if (objection_custom != "" && objection_state == 4) { + f_obj_state = QString::number(objection_state) + "&" + + objection_custom; // we add the name of the objection so the + // packet is like: 4&(name of custom obj) + } else f_obj_state = QString::number(objection_state); @@ -1496,8 +1566,9 @@ void Courtroom::on_chat_return_pressed() threading_flash = preemote_flash; for(int i=0; i < frame_emote_checker->frameCount(); i++){ - AOFrameThreadingPre *testfuck = new AOFrameThreadingPre(this, i); - QThreadPool::globalInstance()->start(testfuck); + AOFrameThreadingPre *frame_thread = new AOFrameThreadingPre(this, i); + QThreadPool::globalInstance()->start(frame_thread); + frame_thread->setAutoDelete(true); } QThreadPool::globalInstance()->waitForDone(); preemote_sfx = threading_sfx; @@ -1525,8 +1596,9 @@ void Courtroom::on_chat_return_pressed() threading_prefix = QString("(b)"); for(int i=0; i < frame_emote_checker->frameCount(); i++){ - AOFrameThreading *testfuck = new AOFrameThreading(this, i); - QThreadPool::globalInstance()->start(testfuck); + AOFrameThreading *frame_thread = new AOFrameThreading(this, i); + QThreadPool::globalInstance()->start(frame_thread); + frame_thread->setAutoDelete(true); } QThreadPool::globalInstance()->waitForDone(); @@ -1554,8 +1626,9 @@ void Courtroom::on_chat_return_pressed() threading_flash = idleemote_flash; threading_prefix = QString("(a)"); for(int i=0; i < frame_emote_checker->frameCount(); i++){ - AOFrameThreading *testfuck = new AOFrameThreading(this, i); - QThreadPool::globalInstance()->start(testfuck); + AOFrameThreading *frame_thread = new AOFrameThreading(this, i); + QThreadPool::globalInstance()->start(frame_thread); + frame_thread->setAutoDelete(true); } QThreadPool::globalInstance()->waitForDone(); idleemote_sfx = threading_sfx; @@ -1578,7 +1651,8 @@ void Courtroom::on_chat_return_pressed() packet_contents.append(frame_screenshake); packet_contents.append(frame_realization); packet_contents.append(frame_sfx); - } + } // Honestly this is a copy paste dump and I have no idea what this does. If + // this breaks blame aov thanks ao_app->send_server_packet(new AOPacket("MS", packet_contents)); } void Courtroom::handle_chatmessage(QStringList *p_contents) @@ -1635,7 +1709,9 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) text_state = 0; anim_state = 0; ui_vp_objection->stop(); + // ui_vp_player_char->stop(); chat_tick_timer->stop(); + if (keep_evidence_display) ui_vp_evidence_display->reset(); chatmessage_is_empty = m_chatmessage[MESSAGE] == " " || m_chatmessage[MESSAGE] == ""; @@ -1644,6 +1720,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) { ui_ic_chat_message->clear(); objection_state = 0; + objection_custom = ""; + char_name = m_chatmessage[CHAR_NAME]; realization_state = 0; screenshake_state = 0; is_presenting_evidence = false; @@ -1655,47 +1733,78 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) ui_realization->set_image("realization.png"); ui_screenshake->set_image("screenshake.png"); ui_evidence_present->set_image("present_disabled.png"); + ui_screenshake->set_image("screenshake.png"); } - chatlogpiece* temp = new chatlogpiece(ao_app->get_showname(char_list.at(f_char_id).name), f_showname, ": " + m_chatmessage[MESSAGE], false); + QString tmpmsg = ""; + chatlogpiece *temp = new chatlogpiece( + ao_app->get_showname(char_list.at(f_char_id).name), f_showname, + ": " + m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); + ic_chatlog_history.append(*temp); while(ic_chatlog_history.size() > log_maximum_blocks && log_maximum_blocks > 0) { ic_chatlog_history.removeFirst(); } + refresh_iclog(true); - append_ic_text(": " + m_chatmessage[MESSAGE], f_showname); + if (f_showname == "") + f_showname = m_chatmessage[CHAR_NAME]; + if (!mirror_iclog) + append_ic_text(": " + m_chatmessage[MESSAGE], f_showname, false, true, + false, m_chatmessage[TEXT_COLOR].toInt()); previous_ic_message = f_message; - - int objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); - QString f_char = m_chatmessage[CHAR_NAME]; + bool ok; + int objection_mod = m_chatmessage[OBJECTION_MOD].toInt( + &ok, 10); // checks if its a custom obj. + QString custom_objection = ""; + if (!ok && m_chatmessage[OBJECTION_MOD].contains("4&")) { + objection_mod = 4; + custom_objection = m_chatmessage[OBJECTION_MOD].split( + "4&")[1]; // takes the name of custom objection. + } + QString f_char = char_name; + f_char = m_chatmessage[CHAR_NAME]; QString f_custom_theme = ao_app->get_char_shouts(f_char); - + ui_vp_message->clear(); + ui_vp_chatbox->hide(); //if an objection is used if (objection_mod <= 4 && objection_mod >= 1) { switch (objection_mod) { case 1: - ui_vp_objection->play("holdit", f_char, f_custom_theme); + ui_vp_objection->play("holdit", f_char, f_custom_theme, shout_stay_time); objection_player->play("holdit.wav", f_char, f_custom_theme); break; case 2: - ui_vp_objection->play("objection", f_char, f_custom_theme); + ui_vp_objection->play("objection", f_char, f_custom_theme, + shout_stay_time); objection_player->play("objection.wav", f_char, f_custom_theme); if(ao_app->get_objectmusic()) music_player->kill_loop(); break; case 3: - ui_vp_objection->play("takethat", f_char, f_custom_theme); + ui_vp_objection->play("takethat", f_char, f_custom_theme, + shout_stay_time); objection_player->play("takethat.wav", f_char, f_custom_theme); break; //case 4 is AO2 only case 4: - ui_vp_objection->play("custom", f_char, f_custom_theme); + if (custom_objection != "") { + ui_vp_objection->play("custom_objections/" + custom_objection, f_char, + f_custom_theme, shout_stay_time); + objection_player->play("custom_objections/" + + custom_objection.split('.')[0] + ".wav", + f_char, f_custom_theme); + } + else { + ui_vp_objection->play("custom", f_char, f_custom_theme, + shout_stay_time); objection_player->play("custom.wav", f_char, f_custom_theme); + } break; default: qDebug() << "W: Logic error in objection switch statement!"; @@ -1718,16 +1827,18 @@ void Courtroom::objection_done() void Courtroom::handle_chatmessage_2() { ui_vp_speedlines->stop(); - ui_vp_player_char->stop(); + // ui_vp_player_char->stop(); ui_vp_player_char->frame_sfx_hellstring = m_chatmessage[FRAME_SFX]; - ui_vp_player_char->frame_realization_hellstring = m_chatmessage[FRAME_REALIZATION]; - ui_vp_player_char->frame_screenshake_hellstring = m_chatmessage[FRAME_SCREENSHAKE]; + ui_vp_player_char->frame_realization_hellstring = + m_chatmessage[FRAME_REALIZATION]; + ui_vp_player_char->frame_screenshake_hellstring = + m_chatmessage[FRAME_SCREENSHAKE]; ui_vp_player_char->use_networked_framehell = true; if (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked()) { QString real_name = char_list.at(m_chatmessage[CHAR_ID].toInt()).name; - QString f_showname = ao_app->get_showname(real_name); + QString f_showname = ao_app->get_showname(m_chatmessage[CHAR_NAME]); ui_vp_showname->setText(f_showname); } @@ -1736,10 +1847,8 @@ void Courtroom::handle_chatmessage_2() ui_vp_showname->setText(m_chatmessage[SHOWNAME]); } - ui_vp_message->clear(); - ui_vp_chatbox->hide(); - - QString chatbox = ao_app->get_chat(m_chatmessage[CHAR_NAME]); + QString f_char = m_chatmessage[CHAR_NAME]; + QString chatbox = ao_app->get_chat(f_char); if (chatbox == "") ui_vp_chatbox->set_image("chatmed.png"); @@ -1795,6 +1904,8 @@ void Courtroom::handle_chatmessage_2() ui_vp_player_char->set_flipped(false); QString side = m_chatmessage[SIDE]; + if (side != "wit") + ui_vp_testimony->stop(); // Making the second character appear. if (m_chatmessage[OTHER_CHARID].isEmpty()) @@ -1952,6 +2063,7 @@ void Courtroom::handle_chatmessage_2() qDebug() << "W: invalid emote mod: " << QString::number(emote_mod); } } +void Courtroom::realization_done() { ui_vp_realization->hide(); } void Courtroom::doScreenShake() { @@ -2004,8 +2116,40 @@ void Courtroom::doScreenShake() void Courtroom::handle_chatmessage_3() { - start_chat_ticking(); + if (!log_goes_downwards && mirror_iclog) + ui_ic_chatlog->moveCursor(QTextCursor::Start); + else if (mirror_iclog) + ui_ic_chatlog->moveCursor(QTextCursor::End); + + ui_ic_chatlog->setTextInteractionFlags(Qt::TextSelectableByMouse); + if (mirror_iclog) { + if (!ui_showname_enable->isChecked() || m_chatmessage[SHOWNAME] == "") { + if (first_message_sent && log_goes_downwards) + ui_ic_chatlog->textCursor().insertHtml("
"); + else + first_message_sent = true; + + ui_ic_chatlog->textCursor().insertHtml("" + m_chatmessage[CHAR_NAME] + + ": "); + } + else { + if (first_message_sent && log_goes_downwards) + ui_ic_chatlog->textCursor().insertHtml("
"); + else + first_message_sent = true; + + ui_ic_chatlog->textCursor().insertHtml("" + m_chatmessage[SHOWNAME] + + ": "); + } + + QScrollBar *scroll = ui_vp_message->verticalScrollBar(); + scroll->setValue(scroll->maximum()); + if (chatmessage_is_empty && log_goes_downwards) { + ui_ic_chatlog->moveCursor(QTextCursor::End); + } + } + start_chat_ticking(); int f_evi_id = m_chatmessage[EVIDENCE_ID].toInt(); QString f_side = m_chatmessage[SIDE]; @@ -2062,7 +2206,9 @@ void Courtroom::handle_chatmessage_3() return; ui_vp_player_char->stop(); - QString f_char = m_chatmessage[CHAR_NAME]; + + QString f_char = ""; + f_char = m_chatmessage[CHAR_NAME]; QString f_emote = m_chatmessage[EMOTE]; if (f_anim_state == 2) { @@ -2091,11 +2237,12 @@ void Courtroom::handle_chatmessage_3() } -QString Courtroom::filter_ic_text(QString p_text) +QString Courtroom::filter_ic_text(QString p_text, bool skip_filter, + int chat_color) { + // BMKCOMMENT // Get rid of centering. - if(p_text.startsWith(": ~~")) - { + if (p_text.startsWith(": ~~")) { // Don't forget, the p_text part actually everything after the name! // Hence why we check for ': ~~'. @@ -2108,139 +2255,243 @@ QString Courtroom::filter_ic_text(QString p_text) // Get rid of the inline-colouring. // I know, I know, excessive code duplication. // Nobody looks in here, I'm fine. - int trick_check_pos = 0; + int trick_check_pos = 1; bool ic_next_is_not_special = false; QString f_character = p_text.at(trick_check_pos); std::stack ic_colour_stack; - while (trick_check_pos < p_text.size()) - { + QString final_text = ": "; + bool delay_pop = false; + while (trick_check_pos < p_text.size()) { f_character = p_text.at(trick_check_pos); - + if (!skip_filter) { + if (f_character == "<") + f_character = "<"; + else if (f_character == ">") + f_character = ">"; + } // Escape character. - if (f_character == "\\" and !ic_next_is_not_special) - { + if (f_character == "\\" and !ic_next_is_not_special) { ic_next_is_not_special = true; p_text.remove(trick_check_pos,1); + f_character = ""; + if (p_text[trick_check_pos] == 'n') { + p_text[trick_check_pos] = ' '; + f_character = " "; + } } // Text speed modifier. - else if (f_character == "{" and !ic_next_is_not_special) - { + else if ((f_character == "{" || f_character == "}") && + !ic_next_is_not_special) { p_text.remove(trick_check_pos,1); + f_character = ""; } - else if (f_character == "}" and !ic_next_is_not_special) - { + else if (f_character == "$" and !ic_next_is_not_special) { p_text.remove(trick_check_pos,1); + f_character = ""; } - - else if (f_character == "$" and !ic_next_is_not_special) - { + else if (f_character == "@" and !ic_next_is_not_special) { p_text.remove(trick_check_pos,1); + f_character = ""; } - else if (f_character == "@" and !ic_next_is_not_special) - { - p_text.remove(trick_check_pos,1); - } - - // Orange inline colourisation. - else if (f_character == "|" and !ic_next_is_not_special) - { - if (!ic_colour_stack.empty()) - { - if (ic_colour_stack.top() == INLINE_ORANGE) - { + else if (f_character == "|" and !ic_next_is_not_special) { + if (!ic_colour_stack.empty()) { + if (ic_colour_stack.top() == INLINE_ORANGE) { ic_colour_stack.pop(); p_text.remove(trick_check_pos,1); } - else - { + else { ic_colour_stack.push(INLINE_ORANGE); p_text.remove(trick_check_pos,1); } } - else - { + else { ic_colour_stack.push(INLINE_ORANGE); p_text.remove(trick_check_pos,1); } + f_character = ""; } // Blue inline colourisation. - else if (f_character == "(" and !ic_next_is_not_special) - { + else if (f_character == "(" and !ic_next_is_not_special) { ic_colour_stack.push(INLINE_BLUE); + if (!colorf_iclog) trick_check_pos++; } - else if (f_character == ")" and !ic_next_is_not_special - and !ic_colour_stack.empty()) - { - if (ic_colour_stack.top() == INLINE_BLUE) - { - ic_colour_stack.pop(); + else if (f_character == ")" and !ic_next_is_not_special and + !ic_colour_stack.empty()) { + if (ic_colour_stack.top() == INLINE_BLUE) { + // ic_colour_stack.pop(); + delay_pop = true; + if (!colorf_iclog) trick_check_pos++; } - else - { + else { ic_next_is_not_special = true; } } // Grey inline colourisation. - else if (f_character == "[" and !ic_next_is_not_special) - { + else if (f_character == "[" and !ic_next_is_not_special) { ic_colour_stack.push(INLINE_GREY); + if (!colorf_iclog) trick_check_pos++; } - else if (f_character == "]" and !ic_next_is_not_special - and !ic_colour_stack.empty()) - { - if (ic_colour_stack.top() == INLINE_GREY) - { - ic_colour_stack.pop(); + else if (f_character == "]" and !ic_next_is_not_special and + !ic_colour_stack.empty()) { + if (ic_colour_stack.top() == INLINE_GREY) { + // ic_colour_stack.pop(); + delay_pop = true; + if (!colorf_iclog) trick_check_pos++; } - else - { + else { ic_next_is_not_special = true; } } // Green inline colourisation. - else if (f_character == "`" and !ic_next_is_not_special) - { - if (!ic_colour_stack.empty()) - { - if (ic_colour_stack.top() == INLINE_GREEN) - { + else if (f_character == "`" and !ic_next_is_not_special) { + if (!ic_colour_stack.empty()) { + if (ic_colour_stack.top() == INLINE_GREEN) { ic_colour_stack.pop(); p_text.remove(trick_check_pos,1); } - else - { + else { ic_colour_stack.push(INLINE_GREEN); p_text.remove(trick_check_pos,1); } } - else - { + else { ic_colour_stack.push(INLINE_GREEN); p_text.remove(trick_check_pos,1); } + f_character = ""; } - else - { - trick_check_pos++; + + if (colorf_iclog && f_character != "") { ic_next_is_not_special = false; + if (!ic_colour_stack.empty()) { + // p_text.remove(trick_check_pos,1); + trick_check_pos++; + switch (ic_colour_stack.top()) { + case INLINE_ORANGE: + final_text += "" + + f_character + ""; + break; + case INLINE_BLUE: + final_text += "" + + f_character + ""; + break; + case INLINE_GREEN: + final_text += "" + + f_character + ""; + break; + case INLINE_GREY: + final_text += "" + + f_character + ""; + break; + } + if (delay_pop) { + ic_colour_stack.pop(); + delay_pop = false; + } + } + else if (!(chat_color == WHITE || chat_color == RAINBOW) && + !colorf_limit) { + trick_check_pos++; + QString html_color; + switch (chat_color) { + case 1: + html_color = get_text_color(QString::number(GREEN)).name(); + break; + case 2: + html_color = get_text_color(QString::number(RED)).name(); + break; + case 3: + html_color = get_text_color(QString::number(ORANGE)).name(); + break; + case 4: + html_color = get_text_color(QString::number(BLUE)).name(); + break; + case 5: + html_color = get_text_color(QString::number(YELLOW)).name(); + break; + case 7: + html_color = get_text_color(QString::number(PINK)).name(); + break; + case 8: + html_color = get_text_color(QString::number(CYAN)).name(); + break; + } + final_text += + "" + f_character + ""; + } + else if (chat_color == RAINBOW && !colorf_limit) { + QString html_color; + + switch (rainbow_counter) { + case 0: + html_color = get_text_color(QString::number(RED)).name(); + break; + case 1: + html_color = get_text_color(QString::number(ORANGE)).name(); + break; + case 2: + html_color = get_text_color(QString::number(YELLOW)).name(); + break; + case 3: + html_color = get_text_color(QString::number(GREEN)).name(); + break; + default: + html_color = get_text_color(QString::number(BLUE)).name(); + rainbow_counter = -1; + } + + ++rainbow_counter; + final_text += + "" + f_character + ""; + trick_check_pos++; + } + + else { + final_text += f_character; + trick_check_pos++; + } + } + else if (f_character != "") { + trick_check_pos++; } } + if (colorf_iclog) + return final_text; + else { return p_text; } +} +/* + * Appends text to the ic log. + * \param p_text The text to be appended + * \param p_name The name of the character/entity who sent said text + * \param is_songchange Whether we are appending a song entry + * \param force_filter If we are sending plain text and we want to force the + * filtering regardless of its status (e.g chat entry, song change etc) \param + * skip_filter If we are sending appending text such as html so we skip the + * filter \param chat_color The color of the message sent + */ -void Courtroom::append_ic_text(QString p_text, QString p_name, bool is_songchange) +void Courtroom::append_ic_text(QString p_text, QString p_name, + bool is_songchange, bool force_filter, + bool skip_filter, int chat_color) { + QTextCharFormat bold; QTextCharFormat normal; QTextCharFormat italics; @@ -2250,97 +2501,138 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, bool is_songchang const QTextCursor old_cursor = ui_ic_chatlog->textCursor(); const int old_scrollbar_value = ui_ic_chatlog->verticalScrollBar()->value(); - if (!is_songchange) - p_text = filter_ic_text(p_text); + if ((!is_songchange && !mirror_iclog) || force_filter) + p_text = filter_ic_text(p_text, skip_filter, chat_color); - if (log_goes_downwards) - { - const bool is_scrolled_down = old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->maximum(); + if (log_goes_downwards) { + const bool is_scrolled_down = + old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->maximum(); ui_ic_chatlog->moveCursor(QTextCursor::End); - + if (!(is_songchange && mirror_iclog)) { + // The only case where no new log entry should be made is when there is a + // music entry while mirror log is active This is to protect the log, as + // if there is a songchange during a new message being typed, then they + // will destructively interfere with eachother + + // If the first message hasn't been sent, and we are handling basic + // text, we put the name without the newline. if (!first_message_sent) - { ui_ic_chatlog->textCursor().insertText(p_name, bold); - first_message_sent = true; - } - else - { + + else if (force_filter || is_songchange || !mirror_iclog) { + // Otherwise we just add the plaintext with the new line. ui_ic_chatlog->textCursor().insertText('\n' + p_name, bold); } + first_message_sent = true; - if (is_songchange) - { + if (is_songchange) { + // If its a song with mirror mode enabled, we do not need to repeat it + // as it is already shown in the ooc. ui_ic_chatlog->textCursor().insertText(" has played a song: ", normal); ui_ic_chatlog->textCursor().insertText(p_text + ".", italics); } - else - { - ui_ic_chatlog->textCursor().insertText(p_text, normal); + + else if (colorf_iclog && (!mirror_iclog || force_filter)) { + // if we are handling already formatted text and we have enabled colors + // in the iclog, then we insert the text + ui_ic_chatlog->textCursor().insertHtml(p_text); } + else if ((!colorf_iclog && !mirror_iclog) || force_filter) { + // If html is not enabled then we insert it as plain text. + ui_ic_chatlog->textCursor().insertText(p_text, normal); + } + } // If we got too many blocks in the current log, delete some from the top. - while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks && log_maximum_blocks > 0) - { + while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks && + log_maximum_blocks > 0) { ui_ic_chatlog->moveCursor(QTextCursor::Start); ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor); ui_ic_chatlog->textCursor().removeSelectedText(); ui_ic_chatlog->textCursor().deleteChar(); - //qDebug() << ui_ic_chatlog->document()->blockCount() << " < " << log_maximum_blocks; + // qDebug() << ui_ic_chatlog->document()->blockCount() << " < " << + // log_maximum_blocks; } - if (old_cursor.hasSelection() || !is_scrolled_down) - { - // The user has selected text or scrolled away from the bottom: maintain position. + if (old_cursor.hasSelection() || !is_scrolled_down) { + // The user has selected text or scrolled away from the bottom: maintain + // position. ui_ic_chatlog->setTextCursor(old_cursor); ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value); } - else - { - // The user hasn't selected any text and the scrollbar is at the bottom: scroll to the bottom. + else { + // The user hasn't selected any text and the scrollbar is at the bottom: + // scroll to the bottom. ui_ic_chatlog->moveCursor(QTextCursor::End); - ui_ic_chatlog->verticalScrollBar()->setValue(ui_ic_chatlog->verticalScrollBar()->maximum()); + ui_ic_chatlog->verticalScrollBar()->setValue( + ui_ic_chatlog->verticalScrollBar()->maximum()); } } - else - { - const bool is_scrolled_up = old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->minimum(); + else { + const bool is_scrolled_up = + old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->minimum(); ui_ic_chatlog->moveCursor(QTextCursor::Start); + if (!(is_songchange && mirror_iclog)) { + // The only case where no new log entry should be made is when there is a + // music entry while mirror log is active This is to protect the log, as + // if there is a songchange during a new message being typed, then they + // will destructively interfere with eachother + + if ((force_filter || !mirror_iclog || is_songchange)) { + + if (mirror_iclog) + // If mirror is enabled we need to make space on the top so the text + // can be inserted without any interuptions If mirror mode is not + // enabled, then we do not need to clear out the top line as the new + // entry pushes it automatically down. + p_name = '\n' + p_name; + + if (!first_message_sent) + first_message_sent = true; ui_ic_chatlog->textCursor().insertText(p_name, bold); + } - if (is_songchange) - { + if (is_songchange) { ui_ic_chatlog->textCursor().insertText(" has played a song: ", normal); ui_ic_chatlog->textCursor().insertText(p_text + "." + '\n', italics); } - else - { - ui_ic_chatlog->textCursor().insertText(p_text + '\n', normal); - } - // If we got too many blocks in the current log, delete some from the bottom. - while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks && log_maximum_blocks > 0) - { + else if (colorf_iclog && (!mirror_iclog || force_filter)) { + ui_ic_chatlog->textCursor().insertHtml(p_text); + } + else if ((!colorf_iclog && !mirror_iclog) || force_filter) { + ui_ic_chatlog->textCursor().insertText(p_text, normal); + } + if (!mirror_iclog) + ui_ic_chatlog->textCursor().insertHtml("
"); + } + // If we got too many blocks in the current log, delete some from the + // bottom. + while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks && + log_maximum_blocks > 0) { ui_ic_chatlog->moveCursor(QTextCursor::End); ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor); ui_ic_chatlog->textCursor().removeSelectedText(); ui_ic_chatlog->textCursor().deletePreviousChar(); - //qDebug() << ui_ic_chatlog->document()->blockCount() << " < " << log_maximum_blocks; + // qDebug() << ui_ic_chatlog->document()->blockCount() << " < " << + // log_maximum_blocks; } - if (old_cursor.hasSelection() || !is_scrolled_up) - { - // The user has selected text or scrolled away from the top: maintain position. + if (old_cursor.hasSelection() || !is_scrolled_up) { + // The user has selected text or scrolled away from the top: maintain + // position. ui_ic_chatlog->setTextCursor(old_cursor); ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value); } - else - { - // The user hasn't selected any text and the scrollbar is at the top: scroll to the top. + else { + // The user hasn't selected any text and the scrollbar is at the top: + // scroll to the top. ui_ic_chatlog->moveCursor(QTextCursor::Start); - ui_ic_chatlog->verticalScrollBar()->setValue(ui_ic_chatlog->verticalScrollBar()->minimum()); + ui_ic_chatlog->verticalScrollBar()->setValue( + ui_ic_chatlog->verticalScrollBar()->minimum()); } } } @@ -2395,18 +2687,12 @@ void Courtroom::preanim_done() handle_chatmessage_3(); } -void Courtroom::realization_done() -{ - ui_vp_realization->hide(); -} - void Courtroom::doRealization() { + realization_timer->stop(); if(!ao_app->is_shakeandflash_enabled()) return; - realization_timer->start(60); - ui_vp_realization->show(); - + ui_vp_realization->play("realizationflash", "", "", 90); } void Courtroom::start_chat_ticking() @@ -2455,7 +2741,8 @@ void Courtroom::start_chat_ticking() current_display_speed = 3; chat_tick_timer->start(message_display_speed[current_display_speed]); - QString f_gender = ao_app->get_gender(m_chatmessage[CHAR_NAME]); + QString f_char = m_chatmessage[CHAR_NAME]; + QString f_gender = ao_app->get_gender(f_char); blip_player->set_blips(ao_app->get_sfx_suffix("sfx-blip" + f_gender)); @@ -2467,12 +2754,15 @@ void Courtroom::chat_tick() { //note: this is called fairly often(every 60 ms when char is talking) //do not perform heavy operations here - + QString timem = QString::number(realization_timer->remainingTime()); + qDebug() << "TIME: " << timem; QString f_message = m_chatmessage[MESSAGE]; + // f_message.remove(0, tick_pos); SAFECHECK + // Due to our new text speed system, we always need to stop the timer now. chat_tick_timer->stop(); - + int msg_delay = message_display_speed[current_display_speed]; // Stops blips from playing when we have a formatting option. bool formatting_char = false; @@ -2482,205 +2772,266 @@ void Courtroom::chat_tick() { f_message.remove(0,2); } + QString f_char = m_chatmessage[CHAR_NAME]; + if (log_goes_downwards && mirror_iclog) + ui_ic_chatlog->moveCursor(QTextCursor::End); + else if (!log_goes_downwards && mirror_iclog) + // ui_ic_chatlog->setTextCursor(); + ui_ic_chatlog->moveCursor(QTextCursor::EndOfLine); - if (tick_pos >= f_message.size()) - { + if (tick_pos >= f_message.size()) { text_state = 2; - if (anim_state != 4) - { + if (mirror_iclog) { + // After we are finished printing the text we log it in the ic log. + append_ic_text(m_chatmessage[MESSAGE], m_chatmessage[CHAR_NAME], false); + if (log_goes_downwards) + ui_ic_chatlog->moveCursor(QTextCursor::End); + else + ui_ic_chatlog->moveCursor(QTextCursor::Start); + } + if (anim_state != 4) { anim_state = 3; - ui_vp_player_char->play_idle(m_chatmessage[CHAR_NAME], m_chatmessage[EMOTE]); + ui_vp_player_char->play_idle(f_char, m_chatmessage[EMOTE]); } } - else - { + else { QString f_character = f_message.at(tick_pos); + f_character = f_character.toHtmlEscaped(); + if (punctuation_chars.contains(f_character)) { + msg_delay *= punctuation_modifier; + // ui_vp_message->insertPlainText(f_character); + } - if (f_character == " ") + if (f_character == " ") { ui_vp_message->insertPlainText(" "); + if (mirror_iclog) + ui_ic_chatlog->insertPlainText(" "); + } + else if (f_character == "@" and !next_character_is_not_special) { + this->doScreenShake(); + formatting_char = true; + } + else if (f_character == "^" and !next_character_is_not_special) { + this->doRealization(); + + formatting_char = true; + } // Escape character. - else if (f_character == "\\" and !next_character_is_not_special) - { + else if (f_character == "\\") { + if (f_message[tick_pos + 1] == 'n') { + ui_vp_message->insertHtml("
"); + ui_ic_chatlog->insertPlainText(" "); + + tick_pos += 1; + next_character_is_not_special = false; + formatting_char = true; + } + else next_character_is_not_special = true; formatting_char = true; + msg_delay++; } // Text speed modifier. - else if (f_character == "{" and !next_character_is_not_special) - { + else if (f_character == "{" and !next_character_is_not_special) { // ++, because it INCREASES delay! current_display_speed++; + msg_delay++; formatting_char = true; } - else if (f_character == "}" and !next_character_is_not_special) - { + else if (f_character == "}" and !next_character_is_not_special) { current_display_speed--; + msg_delay++; formatting_char = true; } - else if (f_character == "@" and !next_character_is_not_special) - { + else if (f_character == "@" and !next_character_is_not_special) { this->doScreenShake(); formatting_char = true; } - else if (f_character == "$" and !next_character_is_not_special) - { + else if (f_character == "$" and !next_character_is_not_special) { this->doRealization(); formatting_char = true; } // Orange inline colourisation. - else if (f_character == "|" and !next_character_is_not_special) - { - if (!inline_colour_stack.empty()) - { - if (inline_colour_stack.top() == INLINE_ORANGE) - { + else if (f_character == "|" and !next_character_is_not_special) { + if (!inline_colour_stack.empty()) { + if (inline_colour_stack.top() == INLINE_ORANGE) { inline_colour_stack.pop(); } - else - { + else { inline_colour_stack.push(INLINE_ORANGE); } } - else - { + else { inline_colour_stack.push(INLINE_ORANGE); } formatting_char = true; + msg_delay++; } // Blue inline colourisation. - else if (f_character == "(" and !next_character_is_not_special) + else if (f_character == "(" and + !next_character_is_not_special) // EXAMPLE HERE { inline_colour_stack.push(INLINE_BLUE); - ui_vp_message->insertHtml("" + f_character + ""); - + ui_vp_message->insertHtml("" + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml("" + f_character + ""); // Increase how deep we are in inline blues. inline_blue_depth++; // Here, we check if the entire message is blue. // If it isn't, we stop talking. - if (!entire_message_is_blue and anim_state != 4) - { - QString f_char = m_chatmessage[CHAR_NAME]; + if (!entire_message_is_blue and anim_state != 4) { + f_char = m_chatmessage[CHAR_NAME]; QString f_emote = m_chatmessage[EMOTE]; ui_vp_player_char->play_idle(f_char, f_emote); } } - else if (f_character == ")" and !next_character_is_not_special - and !inline_colour_stack.empty()) - { - if (inline_colour_stack.top() == INLINE_BLUE) - { + else if (f_character == ")" and !next_character_is_not_special and + !inline_colour_stack.empty()) { + if (inline_colour_stack.top() == INLINE_BLUE) { inline_colour_stack.pop(); - ui_vp_message->insertHtml("" + f_character + ""); - + ui_vp_message->insertHtml("" + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml( + "" + f_character + ""); // Decrease how deep we are in inline blues. // Just in case, we do a check if we're above zero, but we should be. - if (inline_blue_depth > 0) - { + if (inline_blue_depth > 0) { inline_blue_depth--; // Here, we check if the entire message is blue. - // If it isn't, we start talking if we have completely climbed out of inline blues. - if (!entire_message_is_blue) - { - // We should only go back to talking if we're out of inline blues, not during a non. int. pre, and not on the last character. - if (inline_blue_depth == 0 and anim_state != 4 and !(tick_pos+1 >= f_message.size())) - { - QString f_char = m_chatmessage[CHAR_NAME]; + // If it isn't, we start talking if we have completely climbed out of + // inline blues. + if (!entire_message_is_blue) { + // We should only go back to talking if we're out of inline blues, + // not during a non. int. pre, and not on the last character. + if (inline_blue_depth == 0 and anim_state != 4 and + !(tick_pos + 1 >= f_message.size())) { + QString f_char = char_name; + f_char = m_chatmessage[CHAR_NAME]; QString f_emote = m_chatmessage[EMOTE]; ui_vp_player_char->play_talking(f_char, f_emote); } } } } - else - { + else { next_character_is_not_special = true; tick_pos--; } } // Grey inline colourisation. - else if (f_character == "[" and !next_character_is_not_special) - { + else if (f_character == "[" and !next_character_is_not_special) { inline_colour_stack.push(INLINE_GREY); - ui_vp_message->insertHtml("" + f_character + ""); - } - else if (f_character == "]" and !next_character_is_not_special - and !inline_colour_stack.empty()) - { - if (inline_colour_stack.top() == INLINE_GREY) - { + ui_vp_message->insertHtml("" + + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml("" + f_character + ""); + } + else if (f_character == "]" and !next_character_is_not_special and + !inline_colour_stack.empty()) { + if (inline_colour_stack.top() == INLINE_GREY) { inline_colour_stack.pop(); - ui_vp_message->insertHtml("" + f_character + ""); - } - else - { + ui_vp_message->insertHtml("" + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml("" + f_character + ""); + } + else { next_character_is_not_special = true; tick_pos--; } } // Green inline colourisation. - else if (f_character == "`" and !next_character_is_not_special) - { - if (!inline_colour_stack.empty()) - { - if (inline_colour_stack.top() == INLINE_GREEN) - { + else if (f_character == "`" and !next_character_is_not_special) { + if (!inline_colour_stack.empty()) { + if (inline_colour_stack.top() == INLINE_GREEN) { inline_colour_stack.pop(); - formatting_char = true; } - else - { + else { inline_colour_stack.push(INLINE_GREEN); - formatting_char = true; } } - else - { + else { inline_colour_stack.push(INLINE_GREEN); - formatting_char = true; } + msg_delay++; + formatting_char = true; } - else - { + else { + next_character_is_not_special = false; - if (!inline_colour_stack.empty()) - { + if (!inline_colour_stack.empty()) { switch (inline_colour_stack.top()) { case INLINE_ORANGE: - ui_vp_message->insertHtml("" + f_character + ""); + ui_vp_message->insertHtml( + "" + + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml( + "" + + f_character + ""); break; case INLINE_BLUE: - ui_vp_message->insertHtml("" + f_character + ""); + ui_vp_message->insertHtml( + "" + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml( + "" + + f_character + ""); break; case INLINE_GREEN: - ui_vp_message->insertHtml("" + f_character + ""); + ui_vp_message->insertHtml( + "" + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml( + "" + + f_character + ""); break; case INLINE_GREY: - ui_vp_message->insertHtml("" + f_character + ""); - break; - default: - ui_vp_message->insertHtml(f_character); + ui_vp_message->insertHtml("" + f_character + ""); + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml("" + f_character + ""); break; } - } - else - { - if (m_chatmessage[TEXT_COLOR].toInt() == RAINBOW) - { + else { + if (m_chatmessage[TEXT_COLOR].toInt() == RAINBOW) { QString html_color; - switch (rainbow_counter) - { + switch (rainbow_counter) { case 0: html_color = get_text_color(QString::number(RED)).name(); break; @@ -2700,18 +3051,39 @@ void Courtroom::chat_tick() ++rainbow_counter; - ui_vp_message->insertHtml("" + f_character + ""); + ui_vp_message->insertHtml("" + + f_character + ""); + if (mirror_iclog && colorf_iclog && !colorf_limit) + ui_ic_chatlog->insertHtml("" + + f_character + ""); + } + else { + ui_vp_message->insertHtml(f_character); + if (mirror_iclog && colorf_iclog && + ((m_chatmessage[TEXT_COLOR].toInt() == WHITE) || colorf_limit)) + ui_ic_chatlog->insertHtml(f_character); + } + + if (!(m_chatmessage[TEXT_COLOR].toInt() == WHITE) && + !(m_chatmessage[TEXT_COLOR].toInt() == RAINBOW) && !colorf_limit) { + + QString html_color = + get_text_color(QString::number(m_chatmessage[TEXT_COLOR].toInt())) + .name(); + + if (mirror_iclog && colorf_iclog) + ui_ic_chatlog->insertHtml("" + + f_character + ""); } - else - ui_vp_message->insertHtml(f_character); } - if (message_is_centered) - { + if (mirror_iclog && !colorf_iclog) { + ui_ic_chatlog->textCursor().insertHtml(f_character); + } + if (message_is_centered) { ui_vp_message->setAlignment(Qt::AlignCenter); } - else - { + else { ui_vp_message->setAlignment(Qt::AlignLeft); } } @@ -2722,11 +3094,9 @@ void Courtroom::chat_tick() if(blank_blip) qDebug() << "blank_blip found true"; - if (f_message.at(tick_pos) != ' ' || blank_blip) - { + if (f_message.at(tick_pos) != ' ' || blank_blip) { - if (blip_pos % blip_rate == 0 && !formatting_char) - { + if (blip_pos % blip_rate == 0 && !formatting_char) { blip_pos = 0; blip_player->blip_tick(); } @@ -2736,49 +3106,20 @@ void Courtroom::chat_tick() ++tick_pos; - // Restart the timer, but according to the newly set speeds, if there were any. - // Keep the speed at bay. - if (current_display_speed < 0) - { + // Restart the timer, but according to the newly set speeds, if there were + // any. Keep the speed at bay. + if (current_display_speed < 0) { current_display_speed = 0; } - if (current_display_speed > 6) - { + if (current_display_speed > 6) { current_display_speed = 6; } - - // If we had a formatting char, we shouldn't wait so long again, as it won't appear! - if (formatting_char) - { + if (formatting_char) { chat_tick_timer->start(1); } - else - { - chat_tick_timer->start(message_display_speed[current_display_speed]); - } - - } -} - -void Courtroom::show_testimony() -{ - if (!testimony_in_progress || m_chatmessage[SIDE] != "wit") - return; - - ui_vp_testimony->show(); - - testimony_show_timer->start(testimony_show_time); -} - -void Courtroom::hide_testimony() -{ - ui_vp_testimony->hide(); - - if (!testimony_in_progress) - return; - - testimony_hide_timer->start(testimony_hide_time); + else { + chat_tick_timer->start(msg_delay); } void Courtroom::play_sfx() @@ -2793,8 +3134,6 @@ void Courtroom::play_sfx() void Courtroom::set_scene() { - if (testimony_in_progress) - show_testimony(); //witness is default if pos is invalid QString f_background = "witnessempty"; @@ -2833,15 +3172,14 @@ void Courtroom::set_scene() f_background = "prohelperstand"; f_desk_image = "prohelperdesk"; } - else if (f_side == "jur" && (file_exists(ao_app->get_background_path("jurystand.png")) || - file_exists(ao_app->get_background_path("jurystand.gif")))) - { + else if (f_side == "jur" && (file_exists(ao_app->get_image_suffix( + ao_app->get_background_path("jurystand"))))) { f_background = "jurystand"; f_desk_image = "jurydesk"; } - else if (f_side == "sea" && (file_exists(ao_app->get_background_path("seancestand.png")) || - file_exists(ao_app->get_background_path("seancestand.gif")))) - { + else if (f_side == "sea" && + (file_exists(ao_app->get_image_suffix( + ao_app->get_background_path("seancestand"))))) { f_background = "seancestand"; f_desk_image = "seancedesk"; } @@ -2889,7 +3227,9 @@ void Courtroom::set_scene() void Courtroom::set_text_color() { - QColor textcolor = ao_app->get_chat_color(m_chatmessage[TEXT_COLOR], ao_app->get_chat(m_chatmessage[CHAR_NAME])); + QString f_char = m_chatmessage[CHAR_NAME]; + QColor textcolor = ao_app->get_chat_color(m_chatmessage[TEXT_COLOR], + ao_app->get_chat(f_char)); ui_vp_message->setTextBackgroundColor(QColor(0,0,0,0)); ui_vp_message->setTextColor(textcolor); @@ -2908,7 +3248,8 @@ void Courtroom::set_text_color() QColor Courtroom::get_text_color(QString color) { - return ao_app->get_chat_color(color, ao_app->get_chat(m_chatmessage[CHAR_NAME])); + QString f_char = m_chatmessage[CHAR_NAME]; + return ao_app->get_chat_color(color, ao_app->get_chat(f_char)); } void Courtroom::set_ip_list(QString p_list) @@ -2962,12 +3303,10 @@ void Courtroom::handle_song(QStringList *p_contents) qDebug() << "playing song "+ao_app->get_music_path(f_song); - if (n_char < 0 || n_char >= char_list.size()) - { - music_player->play(f_song); + if (n_char < 0 || n_char >= char_list.size()) { + music_player->play(ao_app->get_music_prefix(f_song)); } - else - { + else { QString str_char = char_list.at(n_char).name; QString str_show = char_list.at(n_char).name; @@ -2989,58 +3328,60 @@ void Courtroom::handle_song(QStringList *p_contents) music_player->enable_looping = true; } } - if (!mute_map.value(n_char)) - { - chatlogpiece* temp = new chatlogpiece(str_char, str_show, f_song, true); + if (!mute_map.value(n_char)) { + chatlogpiece *temp = new chatlogpiece(str_char, str_show, f_song, true, + m_chatmessage[TEXT_COLOR].toInt()); ic_chatlog_history.append(*temp); - while(ic_chatlog_history.size() > log_maximum_blocks && log_maximum_blocks > 0) - { + while (ic_chatlog_history.size() > log_maximum_blocks && + log_maximum_blocks > 0) { ic_chatlog_history.removeFirst(); } - - append_ic_text(f_song, str_show, true); - music_player->play(f_song); + if (mirror_iclog) // If mirror is enabled, we display the song in the ooc + // chat rather than ic log for a more realistic + // expierence. + { + ui_server_chatlog->append_chatmessage( + str_show, " has played a song: " + f_song_clear + ".", + ao_app->get_color("ooc_server_color", "courtroom_design.ini") + .name(), + true); + } + append_ic_text(f_song_clear, str_show, true); + music_player->play(ao_app->get_music_prefix(f_song)); } } } - void Courtroom::handle_failed_login() { modcall_player->play("./music/failed_login"); // aov memes } - void Courtroom::handle_wtce(QString p_wtce, int variant) { QString sfx_file = "courtroom_sounds.ini"; //witness testimony - if (p_wtce == "testimony1") - { + if (p_wtce == "testimony1") { misc_sfx_player->play(ao_app->get_sfx("witness_testimony")); - ui_vp_wtce->play("witnesstestimony"); - testimony_in_progress = true; - show_testimony(); + ui_vp_wtce->play("witnesstestimony", "", "", wtce_stay_time); + ui_vp_testimony->play("testimony"); } //cross examination - else if (p_wtce == "testimony2") - { + else if (p_wtce == "testimony2") { misc_sfx_player->play(ao_app->get_sfx("cross_examination")); - ui_vp_wtce->play("crossexamination"); - testimony_in_progress = false; + ui_vp_wtce->play("crossexamination", "", "", wtce_stay_time); + ui_vp_testimony->stop(); } - else if (p_wtce == "judgeruling") - { - if (variant == 0) - { + else if (p_wtce == "judgeruling") { + if (variant == 0) { misc_sfx_player->play(ao_app->get_sfx("not_guilty")); - ui_vp_wtce->play("notguilty"); - testimony_in_progress = false; + ui_vp_wtce->play("notguilty", "", "", verdict_stay_time); + ui_vp_testimony->stop(); } else if (variant == 1) { misc_sfx_player->play(ao_app->get_sfx("guilty")); - ui_vp_wtce->play("guilty"); - testimony_in_progress = false; + ui_vp_wtce->play("guilty", "", "", verdict_stay_time); + ui_vp_testimony->stop(); } } } @@ -3379,10 +3720,19 @@ void Courtroom::on_ooc_return_pressed() casefile.endGroup(); } casefile.sync(); - append_server_chatmessage("CLIENT", tr("Succesfully saved, edit doc and cmdoc link on the ini!"), "1"); + append_server_chatmessage( + "CLIENT", tr("Succesfully saved, edit doc and cmdoc link on the ini!"), + "1"); + } + else if (ooc_message.startsWith("/clearooc")) { + ui_server_chatlog->clear(); + ui_ooc_chat_message->clear(); + return; + } + else if (ooc_message.startsWith("/version")) { + append_server_chatmessage("CLIENT", ao_app->get_version_string(), "1"); ui_ooc_chat_message->clear(); return; - } QStringList packet_contents; @@ -3429,6 +3779,13 @@ void Courtroom::on_ooc_toggle_clicked() } } +void Courtroom::on_music_search_keypr() +{ + if (ui_music_search->text() == "") { + ui_music_list->collapseAll(); + } +} + void Courtroom::on_music_search_edited(QString p_text) { //preventing compiler warnings @@ -3572,20 +3929,24 @@ void Courtroom::on_pair_list_clicked(QModelIndex p_index) } } -void Courtroom::on_music_list_double_clicked(QModelIndex p_model) +void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item, + int column) { if (is_muted) return; - QString p_song = music_list.at(music_row_to_number.at(p_model.row())); - - if (!ui_ic_chat_name->text().isEmpty() && ao_app->cccc_ic_support_enabled) - { - ao_app->send_server_packet(new AOPacket("MC#" + p_song + "#" + QString::number(m_cid) + "#" + ui_ic_chat_name->text() + "#%"), false); + column = 1; // Column 1 is always the metadata (which we want) + QString p_song = p_item->text(column); + if (!ui_ic_chat_name->text().isEmpty() && ao_app->cccc_ic_support_enabled) { + ao_app->send_server_packet(new AOPacket("MC#" + p_song + "#" + + QString::number(m_cid) + "#" + + ui_ic_chat_name->text() + "#%"), + false); } - else - { - ao_app->send_server_packet(new AOPacket("MC#" + p_song + "#" + QString::number(m_cid) + "#%"), false); + else { + ao_app->send_server_packet( + new AOPacket("MC#" + p_song + "#" + QString::number(m_cid) + "#%"), + false); } } @@ -3661,6 +4022,7 @@ void Courtroom::on_custom_objection_clicked() { ui_custom_objection->set_image("custom.png"); objection_state = 0; + objection_custom = ""; } else { @@ -3675,10 +4037,23 @@ void Courtroom::on_custom_objection_clicked() ui_ic_chat_message->setFocus(); } -void Courtroom::on_realization_clicked() +void Courtroom::ShowContextMenu(const QPoint &pos) { - if (realization_state == 0) + QPoint globalPos = ui_custom_objection->mapToGlobal(pos); + QAction *selecteditem = custom_obj_menu->exec(globalPos); + if (selecteditem) { + ui_objection->set_image("objection.png"); + ui_take_that->set_image("takethat.png"); + ui_hold_it->set_image("holdit.png"); + ui_custom_objection->set_image("custom_selected.png"); + objection_custom = selecteditem->text(); + objection_state = 4; + } +} + +void Courtroom::on_realization_clicked() { + if (realization_state == 0) { realization_state = 1; ui_realization->set_image("realization_pressed.png"); } @@ -3868,7 +4243,11 @@ void Courtroom::on_change_character_clicked() void Courtroom::on_reload_theme_clicked() { ao_app->reload_theme(); - + punctuation_modifier = ao_app->get_pundelay(); + colorf_iclog = ao_app->get_colored_iclog_enabled(); + mirror_iclog = ao_app->get_iclmir_enabled(); + colorf_limit = ao_app->colorlog_restricted_enabled(); + keep_evidence_display = ao_app->is_keepevi_enabled(); //to update status on the background set_background(current_background); //to update fallback text bools @@ -3967,26 +4346,8 @@ void Courtroom::on_guard_clicked() void Courtroom::on_showname_enable_clicked() { - ui_ic_chatlog->clear(); - first_message_sent = false; - - foreach (chatlogpiece item, ic_chatlog_history) { - if (ui_showname_enable->isChecked()) - { - if (item.get_is_song()) - append_ic_text(item.get_message(), item.get_showname(), true); - else - append_ic_text(item.get_message(), item.get_showname()); - } - else - { - if (item.get_is_song()) - append_ic_text(item.get_message(), item.get_name(), true); - else - append_ic_text(item.get_message(), item.get_name()); - } - } + refresh_iclog(false); ui_ic_chat_message->setFocus(); } @@ -4005,13 +4366,16 @@ void Courtroom::on_evidence_button_clicked() void Courtroom::on_switch_area_music_clicked() { - if (ui_area_list->isHidden()) - { + + if (ui_area_list->isHidden()) { + music_search_par = ui_music_search->text(); + ui_music_search->setText(area_search_par); ui_area_list->show(); ui_music_list->hide(); } - else - { + else { + area_search_par = ui_music_search->text(); + ui_music_search->setText(music_search_par); ui_area_list->hide(); ui_music_list->show(); } @@ -4072,12 +4436,33 @@ Courtroom::~Courtroom() delete blip_player; } -#ifdef BASSAUDIO -#if (defined (_WIN32) || defined (_WIN64)) -void Courtroom::load_bass_opus_plugin() -{ - BASS_PluginLoad("bassopus.dll", 0); +void Courtroom::refresh_iclog(bool skiplast) +{ + ui_ic_chatlog->clear(); + first_message_sent = false; + + foreach (chatlogpiece item, ic_chatlog_history) { + if (skiplast && ic_chatlog_history.last().get_full() == item.get_full()) { + break; + } + if (ui_showname_enable->isChecked()) { + if (item.get_is_song()) + append_ic_text(item.get_message(), item.get_showname(), true, false, + false); + else + append_ic_text(item.get_message(), item.get_showname(), false, true, + true, item.get_chat_color()); } + else { + if (item.get_is_song()) + append_ic_text(item.get_message(), item.get_name(), true, false, true); + else + append_ic_text(item.get_message(), item.get_name(), false, true, false, + item.get_chat_color()); + } + } +} + #elif (defined (LINUX) || defined (__linux__)) void Courtroom::load_bass_opus_plugin() { @@ -4094,3 +4479,6 @@ void Courtroom::load_bass_opus_plugin() #error This operating system is unsupported for bass plugins. #endif #endif +#ifdef BASSAUDIO +#if (defined(_WIN32) || defined(_WIN64)) +void Courtroom::load_bass_opus_plugin() { BASS_PluginLoad("bassopus.dll", 0); } diff --git a/src/lobby.cpp b/src/lobby.cpp index d817266..c590ad5 100644 --- a/src/lobby.cpp +++ b/src/lobby.cpp @@ -272,17 +272,19 @@ void Lobby::on_connect_released() void Lobby::on_about_clicked() { - QString msg = tr("

Attorney Online %1

" + QString msg = + tr("

Attorney Online %1

" "The courtroom drama simulator" "

Source code: " "" "https://github.com/AttorneyOnline/AO2-Client" "

Major development:
" - "OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter" + "OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, " + "Cents02" "

Special thanks:
" "Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), " "Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, " - "Noevain, Cronnicossy") + "Noevain, Cronnicossy, Raidensnake") .arg(ao_app->get_version_string()); QMessageBox::about(this, "About", msg); } @@ -380,7 +382,10 @@ void Lobby::list_favorites() void Lobby::append_chatmessage(QString f_name, QString f_message) { - ui_chatbox->append_chatmessage(f_name, f_message, ao_app->get_color("ooc_default_color", "courtroom_design.ini").name()); + ui_chatbox->append_chatmessage( + f_name, f_message, + ao_app->get_color("ooc_default_color", "courtroom_design.ini").name(), + false); } void Lobby::append_error(QString f_message) diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index b14cd57..d6518a3 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -7,34 +7,19 @@ #include "hardware_functions.h" #include "debug_functions.h" -class AOPacketLoadMusicThreading : public QRunnable -{ -public: - AOApplication *myapp; - QString filename; - bool ismusic; - AOPacketLoadMusicThreading(AOApplication *my_app, QString file_name, bool is_music){ - myapp = my_app; - filename = file_name; - ismusic = is_music; - } - void run() - { - if(ismusic) +void AOPacketLoadMusic(AOApplication *my_app, QString file_name, bool is_music) { - myapp->w_courtroom->append_music(filename); + if (is_music) { + my_app->w_courtroom->append_music(file_name); } - else - { - myapp->w_courtroom->append_area(filename); - myapp->area_count++; + else { + my_app->w_courtroom->append_area(file_name); + my_app->area_count++; } - for (int area_n = 0; area_n < myapp->area_count; area_n++) - { - myapp->w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown"); + for (int area_n = 0; area_n < my_app->area_count; area_n++) { + my_app->w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown"); } } -}; void AOApplication::ms_packet_received(AOPacket *p_packet) { @@ -438,26 +423,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_lobby->set_loading_text(tr("Loading music:\n%1/%2").arg(QString::number(loaded_music)).arg(QString::number(music_list_size))); - if (musiclist_start) - { - w_courtroom->append_music(f_music); - } - else - { - if (is_music_track(f_music)) - { - musiclist_start = true; - areas--; - //w_courtroom->fix_last_area(); - w_courtroom->append_music(f_music); - } - else - { - w_courtroom->append_area(f_music); - areas++; - } - } - for (int area_n = 0; area_n < areas; area_n++) { w_courtroom->arup_append(0, "Unknown", "Unknown", "Unknown"); @@ -515,38 +480,43 @@ void AOApplication::server_packet_received(AOPacket *p_packet) send_server_packet(new AOPacket("RM#%")); } - else if (header == "SM" || header == "FM") - { + + else if (header == "SM") { if (!courtroom_constructed) goto end; - w_courtroom->clear_music(); - w_courtroom->clear_areas(); - - bool musiclist_start = false; + bool musics_time = false; area_count = 0; - for (int n_element = 0 ; n_element < f_contents.size() ; ++n_element) - { - if (!musiclist_start && is_music_track(f_contents.at(n_element))) - { - musiclist_start = true; - continue; + for (int n_element = 0; n_element < f_contents.size(); ++n_element) { + int element2check = n_element + 1; + if (element2check > f_contents.size()) { + element2check = n_element; // I know this is very lazy code but cba + } + if (!musics_time && (f_contents.at(n_element).startsWith("==") || + f_contents.at(element2check).endsWith(".wav") || + f_contents.at(element2check).endsWith(".mp3") || + f_contents.at(element2check).endsWith(".mp4") || + f_contents.at(element2check).endsWith(".ogg") || + f_contents.at(element2check).endsWith(".opus"))) { + musics_time = true; } - AOPacketLoadMusicThreading *music_load = new AOPacketLoadMusicThreading(this, f_contents.at(n_element), musiclist_start); - QThreadPool::globalInstance()->start(music_load); + + // Not everything needs to have a thread. + AOPacketLoadMusic(this, f_contents.at(n_element), musics_time); ++loaded_music; - int total_loading_size = char_list_size * 2 + evidence_list_size + music_list_size; - int loading_value = int(((loaded_chars + generated_chars + loaded_music + loaded_evidence) / static_cast(total_loading_size)) * 100); + int total_loading_size = + char_list_size * 2 + evidence_list_size + music_list_size; + int loading_value = int( + ((loaded_chars + generated_chars + loaded_music + loaded_evidence) / + static_cast(total_loading_size)) * + 100); w_lobby->set_loading_value(loading_value); - w_lobby->set_loading_text(tr("Loading music:\n%1/%2").arg(QString::number(loaded_music)).arg(QString::number(music_list_size))); - if(QThreadPool::globalInstance()->activeThreadCount() == QThreadPool::globalInstance()->maxThreadCount()) - { - QThreadPool::globalInstance()->waitForDone(); //out of order music is bad - } + w_lobby->set_loading_text(tr("Loading music:\n%1/%2") + .arg(QString::number(loaded_music)) + .arg(QString::number(music_list_size))); } - QThreadPool::globalInstance()->waitForDone(); - if (header == "SM") + send_server_packet(new AOPacket("RD#%")); } else if (header == "DONE") @@ -761,6 +731,7 @@ void AOApplication::send_server_packet(AOPacket *p_packet, bool encoded) } else { + qDebug() << "S:" << f_packet; #ifdef DEBUG_NETWORK qDebug() << "S:" << f_packet; #endif diff --git a/src/path_functions.cpp b/src/path_functions.cpp index 72b7acc..3723192 100644 --- a/src/path_functions.cpp +++ b/src/path_functions.cpp @@ -125,6 +125,7 @@ QString AOApplication::get_music_path(QString p_song) } #ifndef CASE_SENSITIVE_FILESYSTEM return get_base_path() + "sounds/music/" + p_song + ".wav"; + ; #else return get_case_sensitive_path(get_base_path() + "sounds/music/" + p_song + ".wav"); #endif diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 1e1c474..1fbb0b5 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -46,6 +46,15 @@ int AOApplication::get_max_log_size() return result; } +int AOApplication::get_pundelay() +{ + int result = configini->value("punctuation_delay", 2).toInt(); + if (result < 1 || result > 3) { + result = 2; + } + return result; +} + bool AOApplication::get_log_goes_downwards() { QString result = configini->value("log_goes_downwards", "false").value(); @@ -154,6 +163,26 @@ QString AOApplication::read_design_ini(QString p_identifier, QString p_design_pa { QSettings settings(p_design_path, QSettings::IniFormat); QVariant value = settings.value(p_identifier); + if (value.isNull()) // Since the value wasn't found, maybe it uses the proper + // config system + { + int last_underscore_index = p_identifier.lastIndexOf( + '_'); // we will use this in order to check wether it is just showname + // or showname_something + if (last_underscore_index != -1) { + p_identifier.replace( + last_underscore_index, 1, + '/'); // we replace the last dash in order to access the category, e.g + // from showname_font -> showname/font + value = settings.value(p_identifier); + } + else if (!settings.value(p_identifier + "/size") + .isNull()) // This is to check whether showname/size exists, + // because size is defined as widgetname = x + { + value = settings.value(p_identifier + "/size"); + } + } if (value.type() == QVariant::StringList) { return value.toStringList().join(","); } else { @@ -368,8 +397,27 @@ QString AOApplication::get_sfx(QString p_identifier) return return_sfx; } +QString AOApplication::get_music_prefix(QString song_to_check) +{ + if (!file_exists(get_music_path(song_to_check))) { + QString mp3_check = get_music_path(song_to_check + ".mp3"); + QString opus_check = get_music_path(song_to_check + ".opus"); + if (file_exists(opus_check)) { + return song_to_check + ".opus"; + } + else if (file_exists(mp3_check)) { + return song_to_check + ".mp3"; + } + return song_to_check + ".wav"; + } + else { + return song_to_check; + } +} + QString AOApplication::get_sfx_suffix(QString sound_to_check) { + if (!file_exists(get_sounds_path(sound_to_check))) { QString mp3_check = get_sounds_path(sound_to_check + ".mp3"); QString opus_check = get_sounds_path(sound_to_check + ".opus"); if (file_exists(opus_check)) @@ -381,16 +429,21 @@ QString AOApplication::get_sfx_suffix(QString sound_to_check) return sound_to_check + ".mp3"; } return sound_to_check + ".wav"; -} + } + else { + return sound_to_check; + } +} QString AOApplication::get_image_suffix(QString path_to_check) { - QString apng_check = path_to_check + ".apng"; - if (file_exists(apng_check)) - { - return apng_check; - } + if (file_exists(path_to_check + ".webp")) + return path_to_check + ".webp"; + if (file_exists(path_to_check + ".apng")) + return path_to_check + ".apng"; + if (file_exists(path_to_check + ".gif")) return path_to_check + ".gif"; + return path_to_check + ".png"; } @@ -655,9 +708,9 @@ bool AOApplication::is_discord_enabled() return result.startsWith("true"); } -bool AOApplication::is_shakeandflash_enabled() +bool AOApplication::is_keepevi_enabled() { - QString result = configini->value("shakeandflash", "true").value(); + QString result = configini->value("keep_evidence", "false").value(); return result.startsWith("true"); } @@ -715,3 +768,29 @@ QString AOApplication::get_casing_can_host_cases() QString result = configini->value("casing_can_host_cases", "Turnabout Check Your Settings").value(); return result; } + +bool AOApplication::get_colored_iclog_enabled() +{ + QString result = + configini->value("color_iclog_enabled", "false").value(); + return result.startsWith("true"); +} + +bool AOApplication::get_iclmir_enabled() +{ + QString result = + configini->value("mirror_iclog_enabled", "false").value(); + return result.startsWith("true"); +} +bool AOApplication::colorlog_restricted_enabled() +{ + QString result = + configini->value("mirror_iclog_restricted", "false").value(); + return result.startsWith("true"); +} + +bool AOApplication::is_shakeandflash_enabled() +{ + QString result = configini->value("shakeandflash", "true").value(); + return result.startsWith("true"); +}