diff options
| author | Salanto <62221668+Salanto@users.noreply.github.com> | 2023-05-31 20:17:30 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-31 20:17:30 +0200 |
| commit | 7c1fe80d4cbece55149b6fd52e3e90515f440446 (patch) | |
| tree | 2fc87a7cfb5bf9dbb81f52c857a769a6413e8b14 /src | |
| parent | 2915f4cc04c75f02d5c6c89e497193bb981c34b5 (diff) | |
2.10.1 Changes (#888)
* Utilise .ui file to create settings dialog (#858)
* Remove config loading from AOApplications
Removes most, but not all config functions from AOApplication and moves them into their own class.
Not even remotely done here. but holy shit I'm tired.
* First steps towards UI file
* Fixed your UI layout issue
* Leifa bullies me
* Set all the setters
Reminder : Figure out why username and ooc_name exist. Are they the same? Maybe. Maybe not. Gonna have to look at it and migrate the key.
Todo : Cleanup key naming. Most of these are terrible, imprecise or I just don't like them.
* Make layout appear proper
* Minor option dialog update
* Hookup AOOptionsdialogue to Options Getter/setter
Not done yet, but parts of the options interactions work again.
* More settings menu working
* Mostly working settings dialogue
Restore default and cancel still need work
* Fix asset widget
* Tooltips
Also removes the commented out tooltip code
* Finish Tooltips
Move widget implementation to its own folder
* Migrate callwords to config.ini
Also correct sleep deprived code.
* Fix widget translation
* Language dropdown changes
We might want to look into doing this a bit better.
* Remove QSettings from AOApplication
Try cleaning up stray references to said object anymore
* Fix constructor order to prevent runtime crash
* Slightly sort implementation file
* Remove unused label declarations from header
Fix some comments
* Formatting
* Fix buttons
Also fixes restore settings when a restore to default is aborted.
* Raise pair list after courtroom construction (#859)
* Don't reset evidence selection (#860)
They are defaulted in the header. This SHOULD not affect the client negatively.
* Hitting the emergency exit (#861)
Don't change the widget state when the ID exceeds the current widget list due to pages being changed while evidence is being edited.
* add CI and license badge
* add contributors
* Handle config.temp after confirmation
* Deletes config.temp when the user has confirmed they want to keep the current settings.
* Make reset to default destructive
Don't worry, we ask first! :)
* Fix case of self_offset received without a y offset (#864)
caused by typos in #701
it's possible for older clients to send x offsets without a y
offset. if you think this case is annoying you can remove it in
the next version and handle it server-side instead
* Change default settings (#839)
* Make default config enable features for most cases except for Continuous Playback due to it introducing performance issues according to tooltip and confirmed in testing
* Increase log size to 1000
* Default disable animated themes
Co-authored-by: Salanto <62221668+Salanto@users.noreply.github.com>
Co-authored-by: stonedDiscord <Tukz@gmx.de>
* Make it a singleton? Maybe? I dunno? Ask Longbyte
* Commit suggestions
* More suggestions
Also try fixing a memory leak. Not going to well.
* Return to dialog
Otherwise we don't have Exec.
* Cleanup
* Deprecate ooc_name, implement username
* Remove ooc_name key and copy its value to default_showname if its empty.
* Consistent naming in AOOptionsDialog
* Clang format
* Don't write the username to the showname
* Fix theme dropdown being incorrectly set
* Bandaid callword playing every message
* Remove unused or duplicate includes
* More include removals
Removes lobby and courtroom direct includes from the dialog source
* Burn baby, burn!
* Remove reload_theme function
* Remove "Case Alert Supported Message"
All servers I tested on master supported it. The text is redundant in operation.
Co-authored-by: TrickyLeifa <date.epoch@gmail.com>
Co-authored-by: stonedDiscord <Tukz@gmx.de>
Co-authored-by: oldmud0 <oldmud0@users.noreply.github.com>
Co-authored-by: Crystalwarrior <Varsash@Gmail.com>
* Cleanup lobby (#880)
* Remove config loading from AOApplications
Removes most, but not all config functions from AOApplication and moves them into their own class.
Not even remotely done here. but holy shit I'm tired.
* First steps towards UI file
* Fixed your UI layout issue
* Leifa bullies me
* Set all the setters
Reminder : Figure out why username and ooc_name exist. Are they the same? Maybe. Maybe not. Gonna have to look at it and migrate the key.
Todo : Cleanup key naming. Most of these are terrible, imprecise or I just don't like them.
* Make layout appear proper
* Minor option dialog update
* Hookup AOOptionsdialogue to Options Getter/setter
Not done yet, but parts of the options interactions work again.
* More settings menu working
* Mostly working settings dialogue
Restore default and cancel still need work
* Fix asset widget
* Tooltips
Also removes the commented out tooltip code
* Finish Tooltips
Move widget implementation to its own folder
* Migrate callwords to config.ini
Also correct sleep deprived code.
* Fix widget translation
* Language dropdown changes
We might want to look into doing this a bit better.
* Remove QSettings from AOApplication
Try cleaning up stray references to said object anymore
* Fix constructor order to prevent runtime crash
* Slightly sort implementation file
* Remove unused label declarations from header
Fix some comments
* Formatting
* Fix buttons
Also fixes restore settings when a restore to default is aborted.
* Raise pair list after courtroom construction (#859)
* Don't reset evidence selection (#860)
They are defaulted in the header. This SHOULD not affect the client negatively.
* Hitting the emergency exit (#861)
Don't change the widget state when the ID exceeds the current widget list due to pages being changed while evidence is being edited.
* add CI and license badge
* add contributors
* Handle config.temp after confirmation
* Deletes config.temp when the user has confirmed they want to keep the current settings.
* Make reset to default destructive
Don't worry, we ask first! :)
* Fix case of self_offset received without a y offset (#864)
caused by typos in #701
it's possible for older clients to send x offsets without a y
offset. if you think this case is annoying you can remove it in
the next version and handle it server-side instead
* Change default settings (#839)
* Make default config enable features for most cases except for Continuous Playback due to it introducing performance issues according to tooltip and confirmed in testing
* Increase log size to 1000
* Default disable animated themes
Co-authored-by: Salanto <62221668+Salanto@users.noreply.github.com>
Co-authored-by: stonedDiscord <Tukz@gmx.de>
* Make it a singleton? Maybe? I dunno? Ask Longbyte
* Commit suggestions
* More suggestions
Also try fixing a memory leak. Not going to well.
* Return to dialog
Otherwise we don't have Exec.
* Cleanup
* Deprecate ooc_name, implement username
* Remove ooc_name key and copy its value to default_showname if its empty.
* Consistent naming in AOOptionsDialog
* Clang format
* Don't write the username to the showname
* Fix theme dropdown being incorrectly set
* Bandaid callword playing every message
* Remove unused or duplicate includes
* More include removals
Removes lobby and courtroom direct includes from the dialog source
* Burn baby, burn!
* Remove reload_theme function
* Remove "Case Alert Supported Message"
All servers I tested on master supported it. The text is redundant in operation.
* Create preliminary lobby design
Attempts to slightly modernize the aging lobby to a scheme more akin to modern server browsers.
* Fix missing header, add necessary search lineedits
* More UI changes
* Start hooking up new UI elements
* Hookup Serverbrowser to new UI frontend
Still need to fix the favorites AND implement the NEW demolist
* Fixup demo ui and make demoserver functional
* More demoserver cleanup
* Remove jarring ao_app pointer shenigans
Still a bit to do before we can safely remove that pointer, but hey, its something.
* *unholy screeches*
Tried to untangle the tange of dependencies that is connection behaviour
* Rip out loading screen
Some servers are not even sending proper values anymore, like vanilla, so why keep it?
* Optimise includes, format header
Lobby should not even have to know what an AOPacket is, smh
* Formatting fixes
and turn settings menu opening into a signal
* Why does netmanager never emit when the server is connected
* Fixup final parts
About as well implemented as I can do rn. Missing the load screen, but that was more flair than anything else
* Correct start page
* demo qol
Co-authored-by: TrickyLeifa <date.epoch@gmail.com>
Co-authored-by: stonedDiscord <Tukz@gmx.de>
Co-authored-by: oldmud0 <oldmud0@users.noreply.github.com>
Co-authored-by: Crystalwarrior <Varsash@Gmail.com>
* Delete rebase artifact
* only set setting codec on qt5
* fix old regex
* qlocale include was missing
* Add default soundfont value + cleaup stream checks
* Remove Case Announcement
* Add add_server dialog and move logic to options.h
* Add Direction Connection Widget and function
* Visual Fluff, don't show direct connection on demo screen
* Implement ui-file reload and RCC mounting.
* Add edit menu to favorites
* Add Server remains active when no server is selected
* Hack together window title for courtroom
I hate this.
* Fix incorrect subtheme location code
* Cleanup
* Make all charicons appear on first join
This entire system needs a rework, but this will do for now.
Also slightly improves performance by not making it load the character list 4 times, only 2 now :^)
closes #854
* Fix evidence hover selector under Qt5
#closes #890
* Remove options calling itself trough pointer
* Fix Android CI (#891)
* pro gamer move
* remove pregenerated android files
* version
* install old ass android platform
* Revert "remove pregenerated android files"
This reverts commit c81a94c6fd337e187af61e9dd706fac5cd51bcc0.
* switch to 24
* CharButton - Fix enterEvent override in Qt5
Also mark them as override. Also make the preprocessor if a bit less copypastey.
* version bump
* Update embeeded lobby ui color sheme
Shoutout to Dumb Fuck (That is their real discord name).
Co-Authored-By: Crystalwarrior <3470436+Crystalwarrior@users.noreply.github.com>
* Add changelog.md loading logic from main mount path
* Expand tabbar of optional Tabbar widget
* Fix order column being incorrectly sized
* missed a space
* remove fonts
* change margins
* fix minimum sizes
* Allow theme overwrite of settings menu
* Cleanup iterator for subthemes
* Allow reload of settings menu
Might aswell do them all :shrug:
* AO base path (#893)
* make get_base_path global
and move parts that use base to use it
* options uses base
* sal moved a bunch of code
* fix creating case folder
---------
Co-authored-by: stonedDiscord <10584181+stonedDiscord@users.noreply.github.com>
* Android 2 10 1 (#894)
* ask for file permissions before trying to load a file
* create armv7 gitignore
* extract all the abis
* don't fail if the dir exists
* Clear options map before reloading the UI
* Fix runtime warning for theme/subtheme combobox
Shouldn't do the job of something that the template can do for me.
Also fix formatting cause it was busted.
Also made the subtheme/theme load code not give me cancer.
* Sort dropdown numerically to match explorer preview
closes #793
* fuck bass
* copy mingw
* copy other dll
* wrong folder
* Account for server subtheme
* Replace incorrect subtheme check
* Settings, not server
* Remove debug
* Add compatibility code, suppress compiler warning (#896)
lobby.cpp:
* Added compatibility code so 2.10.1 can run on Qt versions older than 5.14, such as the version that ships with Ubuntu 20.04
courtroom.cpp:
* Used a Q_UNUSED macro on an unused variable to suppress a compiler warning
* Resolve Qt6(.5.0) compiler errors
* Undo incompetence.
* Force theme reload on theme change
If a user saves a new theme and does not reload the UI it will cause misplacement of widgets inside of courtroom.
This is mitigated by forcing a reload.
* make speedlines stretch by default (in *actually* non-stupid way this time) (#901)
* Rework default volume settings (#903)
* rework volume default settings
* remove default volume settings in options dialog
* make client remember last volume settings instead
* fix options starting tab
* Reworked direct connect (#906)
Resolve issue #905
Works as advertised.
* Set join text when double-click on connected server
Good enough. I would handle this a bit smarter and lock based on the connection state of NetworkManager, but NetworkManager sucks and I refuse to fix it this close before 2.10.1 is done.
* remove unused m_looping
* remove useless underflow check
* do not fall from server to favorites
* Ci android fix (#899)
* pro gamer move
* remove pregenerated android files
* version
* install old ass android platform
* Revert "remove pregenerated android files"
This reverts commit c81a94c6fd337e187af61e9dd706fac5cd51bcc0.
* switch to 24
* use android\src\android\templates instead
* deprecate "chat" deskmod (#910)
* ignore deskmod when zoom speaking
* clean up deskmod a bit
* adds an enum for deskmods
* deprecates the "chat" deskmood
* modifies set_scene since it never rly used the deskmod argument
meaningfully
* actually use the enums i made lol
* fix typo
* Add credits for lamdacalculus
---------
Co-authored-by: TrickyLeifa <date.epoch@gmail.com>
Co-authored-by: stonedDiscord <Tukz@gmx.de>
Co-authored-by: oldmud0 <oldmud0@users.noreply.github.com>
Co-authored-by: Crystalwarrior <Varsash@Gmail.com>
Co-authored-by: Crystalwarrior <3470436+Crystalwarrior@users.noreply.github.com>
Co-authored-by: stonedDiscord <10584181+stonedDiscord@users.noreply.github.com>
Co-authored-by: segfault <128277930+memsecviolator@users.noreply.github.com>
Co-authored-by: lambdcalculus <64238778+lambdcalculus@users.noreply.github.com>
Co-authored-by: Leifa♥ <26681464+TrickyLeifa@users.noreply.github.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/aoapplication.cpp | 99 | ||||
| -rw-r--r-- | src/aobutton.cpp | 7 | ||||
| -rw-r--r-- | src/aocaseannouncerdialog.cpp | 85 | ||||
| -rw-r--r-- | src/aocharbutton.cpp | 4 | ||||
| -rw-r--r-- | src/aoevidencebutton.cpp | 4 | ||||
| -rw-r--r-- | src/aoimage.cpp | 9 | ||||
| -rw-r--r-- | src/aolayer.cpp | 18 | ||||
| -rw-r--r-- | src/aomusicplayer.cpp | 54 | ||||
| -rw-r--r-- | src/aooptionsdialog.cpp | 1449 | ||||
| -rw-r--r-- | src/charselect.cpp | 47 | ||||
| -rw-r--r-- | src/courtroom.cpp | 342 | ||||
| -rw-r--r-- | src/demoserver.cpp | 10 | ||||
| -rw-r--r-- | src/emotes.cpp | 3 | ||||
| -rw-r--r-- | src/evidence.cpp | 9 | ||||
| -rw-r--r-- | src/file_functions.cpp | 20 | ||||
| -rw-r--r-- | src/lobby.cpp | 832 | ||||
| -rw-r--r-- | src/main.cpp | 14 | ||||
| -rw-r--r-- | src/networkmanager.cpp | 13 | ||||
| -rw-r--r-- | src/options.cpp | 703 | ||||
| -rw-r--r-- | src/packet_distribution.cpp | 107 | ||||
| -rw-r--r-- | src/path_functions.cpp | 30 | ||||
| -rw-r--r-- | src/text_file_functions.cpp | 514 | ||||
| -rw-r--r-- | src/widgets/add_server_dialog.cpp | 96 | ||||
| -rw-r--r-- | src/widgets/aooptionsdialog.cpp | 648 | ||||
| -rw-r--r-- | src/widgets/direct_connect_dialog.cpp | 101 | ||||
| -rw-r--r-- | src/widgets/edit_server_dialog.cpp | 87 |
26 files changed, 2335 insertions, 2970 deletions
diff --git a/src/aoapplication.cpp b/src/aoapplication.cpp index 856b8ada..24682bc2 100644 --- a/src/aoapplication.cpp +++ b/src/aoapplication.cpp @@ -1,12 +1,13 @@ #include "aoapplication.h" +#include "bassmidi.h" #include "courtroom.h" #include "debug_functions.h" #include "lobby.h" #include "networkmanager.h" +#include "options.h" -#include "aocaseannouncerdialog.h" -#include "aooptionsdialog.h" +#include "widgets/aooptionsdialog.h" static QtMessageHandler original_message_handler; static AOApplication *message_handler_context; @@ -19,10 +20,6 @@ void message_handler(QtMsgType type, const QMessageLogContext &context, AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv) { - // Create the QSettings class that points to the config.ini. - configini = - new QSettings(get_base_path() + "config.ini", QSettings::IniFormat); - net_manager = new NetworkManager(this); discord = new AttorneyOnline::Discord(); @@ -40,7 +37,6 @@ AOApplication::~AOApplication() destruct_lobby(); destruct_courtroom(); delete discord; - delete configini; qInstallMessageHandler(original_message_handler); } @@ -51,8 +47,7 @@ void AOApplication::construct_lobby() return; } - load_favorite_list(); - w_lobby = new Lobby(this); + w_lobby = new Lobby(this, net_manager); lobby_constructed = true; QRect geometry = QGuiApplication::primaryScreen()->geometry(); @@ -60,13 +55,12 @@ void AOApplication::construct_lobby() int y = (geometry.height() - w_lobby->height()) / 2; w_lobby->move(x, y); - if (is_discord_enabled()) + if (Options::getInstance().discordEnabled()) discord->state_lobby(); if (demo_server) demo_server->deleteLater(); demo_server = new DemoServer(this); - w_lobby->show(); } @@ -124,64 +118,6 @@ QString AOApplication::get_version_string() QString::number(MINOR_VERSION); } -void AOApplication::reload_theme() { current_theme = read_theme(); } - -void AOApplication::load_favorite_list() -{ - favorite_list = read_favorite_servers(); -} - -void AOApplication::save_favorite_list() -{ - QSettings favorite_servers_ini(get_base_path() + "favorite_servers.ini", QSettings::IniFormat); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - favorite_servers_ini.setIniCodec("UTF-8"); -#endif - - favorite_servers_ini.clear(); - // skip demo server entry, demo server entry is always at index 0 - for(int i = 1; i < favorite_list.size(); ++i) { - auto fav_server = favorite_list.at(i); - favorite_servers_ini.beginGroup(QString::number(i)); - favorite_servers_ini.setValue("name", fav_server.name); - favorite_servers_ini.setValue("address", fav_server.ip); - favorite_servers_ini.setValue("port", fav_server.port); - favorite_servers_ini.setValue("desc", fav_server.desc); - - if (fav_server.socket_type == TCP) { - favorite_servers_ini.setValue("protocol", "tcp"); - } else { - favorite_servers_ini.setValue("protocol", "ws"); - } - favorite_servers_ini.endGroup(); - } - favorite_servers_ini.sync(); -} - -QString AOApplication::get_current_char() -{ - if (courtroom_constructed) - return w_courtroom->get_current_char(); - else - return ""; -} - -void AOApplication::add_favorite_server(int p_server) -{ - if (p_server < 0 || p_server >= server_list.size()) - return; - favorite_list.append(server_list.at(p_server)); - save_favorite_list(); -} - -void AOApplication::remove_favorite_server(int p_server) -{ - if (p_server < 0 || p_server >= favorite_list.size()) - return; - favorite_list.removeAt(p_server); - save_favorite_list(); -} - void AOApplication::server_disconnected() { if (courtroom_constructed) { @@ -189,25 +125,26 @@ void AOApplication::server_disconnected() construct_lobby(); destruct_courtroom(); } + Options::getInstance().setServerSubTheme(QString()); } void AOApplication::loading_cancelled() { destruct_courtroom(); - - w_lobby->hide_loading_overlay(); } void AOApplication::call_settings_menu() { - AOOptionsDialog settings(nullptr, this); - settings.exec(); -} + AOOptionsDialog* l_dialog = new AOOptionsDialog(nullptr, this); + if (courtroom_constructed) { + connect(l_dialog, &AOOptionsDialog::reloadThemeRequest, + w_courtroom, &Courtroom::on_reload_theme_clicked); + } -void AOApplication::call_announce_menu(Courtroom *court) -{ - AOCaseAnnouncerDialog announcer(nullptr, this, court); - announcer.exec(); + if(lobby_constructed) { + } + l_dialog->exec(); + delete l_dialog; } // Callback for when BASS device is lost @@ -238,24 +175,26 @@ void AOApplication::initBASS() unsigned int a = 0; BASS_DEVICEINFO info; - if (get_audio_output_device() == "default") { + if (Options::getInstance().audioOutputDevice() == "default") { BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr); load_bass_plugins(); } else { for (a = 0; BASS_GetDeviceInfo(a, &info); a++) { - if (get_audio_output_device() == info.name) { + if (Options::getInstance().audioOutputDevice() == info.name) { BASS_SetDevice(a); BASS_Init(static_cast<int>(a), 48000, BASS_DEVICE_LATENCY, nullptr, nullptr); load_bass_plugins(); qInfo() << info.name << "was set as the default audio output device."; + BASS_SetConfigPtr(BASS_CONFIG_MIDI_DEFFONT, QString(get_base_path() + "soundfont.sf2").toStdString().c_str()); return; } } BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr); load_bass_plugins(); } + BASS_SetConfigPtr(BASS_CONFIG_MIDI_DEFFONT, QString(get_base_path() + "soundfont.sf2").toStdString().c_str()); } #if (defined(_WIN32) || defined(_WIN64)) diff --git a/src/aobutton.cpp b/src/aobutton.cpp index 6d25a05f..5ef2a066 100644 --- a/src/aobutton.cpp +++ b/src/aobutton.cpp @@ -2,6 +2,7 @@ #include "debug_functions.h" #include "file_functions.h" +#include "options.h" AOButton::AOButton(QWidget *parent, AOApplication *p_ao_app) : QPushButton(parent) @@ -20,8 +21,8 @@ void AOButton::set_image(QString p_path, QString p_misc) { movie->stop(); QString p_image; - p_image = ao_app->get_image(p_path, ao_app->current_theme, ao_app->get_subtheme(), - ao_app->default_theme, p_misc, "", "", !ao_app->get_animated_theme()); + p_image = ao_app->get_image(p_path, Options::getInstance().theme(), Options::getInstance().subTheme(), + ao_app->default_theme, p_misc, "", "", !Options::getInstance().animatedThemeEnabled()); if (p_image.isEmpty()) { this->setIcon(QIcon()); this->setIconSize(this->size()); @@ -33,7 +34,7 @@ void AOButton::set_image(QString p_path, QString p_misc) movie->setFileName(p_image); // We double-check if the user wants animated themes, so even if an animated image slipped through, // we still set it static - if (ao_app->get_animated_theme() && movie->frameCount() > 1) { + if (Options::getInstance().animatedThemeEnabled() && movie->frameCount() > 1) { movie->start(); } else { diff --git a/src/aocaseannouncerdialog.cpp b/src/aocaseannouncerdialog.cpp deleted file mode 100644 index 0c9ee0f3..00000000 --- a/src/aocaseannouncerdialog.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "aocaseannouncerdialog.h" - -AOCaseAnnouncerDialog::AOCaseAnnouncerDialog(QWidget *parent, - AOApplication *p_ao_app, - Courtroom *p_court) - : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) -{ - ao_app = p_ao_app; - court = p_court; - - setWindowTitle(tr("Case Announcer")); - resize(405, 235); - - ui_announcer_buttons = new QDialogButtonBox(this); - - QSizePolicy sizepolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - sizepolicy.setHorizontalStretch(0); - sizepolicy.setVerticalStretch(0); - sizepolicy.setHeightForWidth( - ui_announcer_buttons->sizePolicy().hasHeightForWidth()); - ui_announcer_buttons->setSizePolicy(sizepolicy); - ui_announcer_buttons->setOrientation(Qt::Horizontal); - ui_announcer_buttons->setStandardButtons(QDialogButtonBox::Ok | - QDialogButtonBox::Cancel); - - connect(ui_announcer_buttons, &QDialogButtonBox::accepted, this, - &AOCaseAnnouncerDialog::ok_pressed); - connect(ui_announcer_buttons, &QDialogButtonBox::rejected, this, - &AOCaseAnnouncerDialog::cancel_pressed); - - setUpdatesEnabled(false); - - ui_vbox_layout = new QVBoxLayout(this); - - ui_form_layout = new QFormLayout(this); - ui_form_layout->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft | - Qt::AlignVCenter); - ui_form_layout->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft | - Qt::AlignTop); - ui_form_layout->setContentsMargins(6, 6, 6, 6); - - ui_vbox_layout->addItem(ui_form_layout); - ui_vbox_layout->addWidget(ui_announcer_buttons); - - ui_case_title_label = new QLabel(this); - ui_case_title_label->setText(tr("Case title:")); - - ui_form_layout->setWidget(0, QFormLayout::LabelRole, ui_case_title_label); - - ui_case_title_textbox = new QLineEdit(this); - ui_case_title_textbox->setMaxLength(50); - - ui_form_layout->setWidget(0, QFormLayout::FieldRole, ui_case_title_textbox); - - ui_defense_needed = new QCheckBox(this); - ui_defense_needed->setText(tr("Defense needed")); - ui_prosecutor_needed = new QCheckBox(this); - ui_prosecutor_needed->setText(tr("Prosecution needed")); - ui_judge_needed = new QCheckBox(this); - ui_judge_needed->setText(tr("Judge needed")); - ui_juror_needed = new QCheckBox(this); - ui_juror_needed->setText(tr("Jurors needed")); - ui_steno_needed = new QCheckBox(this); - ui_steno_needed->setText(tr("Stenographer needed")); - - ui_form_layout->setWidget(1, QFormLayout::FieldRole, ui_defense_needed); - ui_form_layout->setWidget(2, QFormLayout::FieldRole, ui_prosecutor_needed); - ui_form_layout->setWidget(3, QFormLayout::FieldRole, ui_judge_needed); - ui_form_layout->setWidget(4, QFormLayout::FieldRole, ui_juror_needed); - ui_form_layout->setWidget(5, QFormLayout::FieldRole, ui_steno_needed); - - setUpdatesEnabled(true); -} - -void AOCaseAnnouncerDialog::ok_pressed() -{ - court->announce_case( - ui_case_title_textbox->text(), ui_defense_needed->isChecked(), - ui_prosecutor_needed->isChecked(), ui_judge_needed->isChecked(), - ui_juror_needed->isChecked(), ui_steno_needed->isChecked()); - - done(0); -} - -void AOCaseAnnouncerDialog::cancel_pressed() { done(0); } diff --git a/src/aocharbutton.cpp b/src/aocharbutton.cpp index 19eff5fc..0c4ff129 100644 --- a/src/aocharbutton.cpp +++ b/src/aocharbutton.cpp @@ -78,7 +78,11 @@ void AOCharButton::set_image(QString p_character) } } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +void AOCharButton::enterEvent(QEvent *e) +#else void AOCharButton::enterEvent(QEnterEvent *e) +#endif { ui_selector->move(this->x() - 1, this->y() - 1); ui_selector->raise(); diff --git a/src/aoevidencebutton.cpp b/src/aoevidencebutton.cpp index ff690c20..d731682e 100644 --- a/src/aoevidencebutton.cpp +++ b/src/aoevidencebutton.cpp @@ -104,7 +104,11 @@ void AOEvidenceButton::dragEnterEvent(QMouseEvent *e) } */ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +void AOEvidenceButton::enterEvent(QEvent *e) +#else void AOEvidenceButton::enterEvent(QEnterEvent *e) +#endif { ui_selector->show(); diff --git a/src/aoimage.cpp b/src/aoimage.cpp index c488a093..e737ffb3 100644 --- a/src/aoimage.cpp +++ b/src/aoimage.cpp @@ -1,6 +1,7 @@ #include "file_functions.h" #include "aoimage.h" +#include "options.h" #include <QBitmap> @@ -28,9 +29,9 @@ AOImage::~AOImage() {} bool AOImage::set_image(QString p_image, QString p_misc) { - QString p_image_resolved = ao_app->get_image(p_image, ao_app->current_theme, ao_app->get_subtheme(), + QString p_image_resolved = ao_app->get_image(p_image, Options::getInstance().theme(), Options::getInstance().subTheme(), ao_app->default_theme, p_misc, "", "", - is_static || !ao_app->get_animated_theme()); + is_static || !Options::getInstance().animatedThemeEnabled()); if (!file_exists(p_image_resolved)) { qWarning() << "could not find image" << p_image; @@ -41,11 +42,11 @@ bool AOImage::set_image(QString p_image, QString p_misc) if (!is_static) { movie->stop(); movie->setFileName(path); - if (ao_app->get_animated_theme() && movie->frameCount() > 1) { + if (Options::getInstance().animatedThemeEnabled() && movie->frameCount() > 1) { movie->start(); } } - if (is_static || !ao_app->get_animated_theme() || movie->frameCount() <= 1) { + if (is_static || !Options::getInstance().animatedThemeEnabled() || movie->frameCount() <= 1) { QPixmap f_pixmap(path); f_pixmap = diff --git a/src/aolayer.cpp b/src/aolayer.cpp index 27ebe48c..f9b01d3b 100644 --- a/src/aolayer.cpp +++ b/src/aolayer.cpp @@ -2,6 +2,8 @@ #include "aoapplication.h" #include "file_functions.h" +#include "misc_functions.h" +#include "options.h" static QThreadPool *thread_pool; @@ -233,7 +235,7 @@ void SplashLayer::load_image(QString p_filename, QString p_charname, QString p_miscname) { transform_mode = ao_app->get_misc_scaling(p_miscname); - QString final_image = ao_app->get_image(p_filename, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_miscname, p_charname, "placeholder"); + QString final_image = ao_app->get_image(p_filename, Options::getInstance().theme(), Options::getInstance().subTheme(), ao_app->default_theme, p_miscname, p_charname, "placeholder"); start_playback(final_image); play(); } @@ -256,7 +258,7 @@ void InterfaceLayer::load_image(QString p_filename, QString p_miscname) { last_path = ""; stretch = true; - QString final_image = ao_app->get_image(p_filename, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_miscname); + QString final_image = ao_app->get_image(p_filename, Options::getInstance().theme(), Options::getInstance().subTheme(), ao_app->default_theme, p_miscname); start_playback(final_image); play(); } @@ -264,10 +266,10 @@ void InterfaceLayer::load_image(QString p_filename, QString p_miscname) void StickerLayer::load_image(QString p_charname) { QString p_miscname; - if (ao_app->is_customchat_enabled()) + if (Options::getInstance().customChatboxEnabled()) p_miscname = ao_app->get_chat(p_charname); transform_mode = ao_app->get_misc_scaling(p_miscname); - QString final_image = ao_app->get_image("sticker/" + p_charname, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_miscname); + QString final_image = ao_app->get_image("sticker/" + p_charname, Options::getInstance().theme(), Options::getInstance().subTheme(), ao_app->default_theme, p_miscname); start_playback(final_image); play(); } @@ -296,7 +298,7 @@ void AOLayer::start_playback(QString p_image) QMutexLocker locker(&mutex); this->show(); - if (!ao_app->is_continuous_enabled()) { + if (!Options::getInstance().continuousPlaybackEnabled()) { continuous = false; force_continuous = true; } @@ -335,11 +337,11 @@ void AOLayer::start_playback(QString p_image) frame = 0; continuous = false; } -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) frame_loader = QtConcurrent::run(thread_pool, this, &AOLayer::populate_vectors); -#else + #else frame_loader = QtConcurrent::run(thread_pool, &AOLayer::populate_vectors, this); -#endif + #endif last_path = p_image; while (movie_frames.size() <= frame) // if we haven't loaded the frame we need yet frameAdded.wait(&mutex); // wait for the frame loader to add another frame, then check again diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp index f29e0cf9..366335a4 100644 --- a/src/aomusicplayer.cpp +++ b/src/aomusicplayer.cpp @@ -1,4 +1,8 @@ #include "aomusicplayer.h" +#include "options.h" + +#include "bass.h" +#include "file_functions.h" AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app) { @@ -30,25 +34,15 @@ QString AOMusicPlayer::play(QString p_song, int channel, bool loop, DWORD newstream; if (f_path.startsWith("http")) { - if (ao_app->is_streaming_disabled()) { + if (!Options::getInstance().streamingEnabled()) { BASS_ChannelStop(m_stream_list[channel]); return QObject::tr("[MISSING] Streaming disabled."); } - - if (f_path.endsWith(".opus")) - newstream = BASS_OPUS_StreamCreateURL(f_path.toStdString().c_str(), 0, streaming_flags, nullptr, 0); - else if (f_path.endsWith(".mid")) - newstream = BASS_MIDI_StreamCreateURL(f_path.toStdString().c_str(), 0, streaming_flags, nullptr, 0, 1); - else - newstream = BASS_StreamCreateURL(f_path.toStdString().c_str(), 0, streaming_flags, nullptr, 0); - - } else { + newstream = BASS_StreamCreateURL(f_path.toStdString().c_str(), 0, streaming_flags, nullptr, 0); + } + else { f_path = ao_app->get_real_path(ao_app->get_music_path(p_song)); - if (f_path.endsWith(".opus")) - newstream = BASS_OPUS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags); - else if (f_path.endsWith(".mid")) - newstream = BASS_MIDI_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags, 1); - else if (f_path.endsWith(".mo3") || f_path.endsWith(".xm") || f_path.endsWith(".mod") || f_path.endsWith(".s3m") || f_path.endsWith(".it") || f_path.endsWith(".mtm") || f_path.endsWith(".umx") ) + if (f_path.endsWith(".mo3") || f_path.endsWith(".xm") || f_path.endsWith(".mod") || f_path.endsWith(".s3m") || f_path.endsWith(".it") || f_path.endsWith(".mtm") || f_path.endsWith(".umx") ) newstream = BASS_MusicLoad(FALSE,f_path.utf16(), 0, 0, flags, 1); else newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags); @@ -56,7 +50,7 @@ QString AOMusicPlayer::play(QString p_song, int channel, bool loop, int error_code = BASS_ErrorGetCode(); - if (ao_app->get_audio_output_device() != "default") + if (Options::getInstance().audioOutputDevice() != "default") BASS_ChannelSetDevice(m_stream_list[channel], BASS_GetDevice()); QString d_path = f_path + ".txt"; @@ -219,20 +213,18 @@ void AOMusicPlayer::set_looping(bool loop_song, int channel) loop_sync[channel] = 0; } - if (loop_start[channel] >= 0) { - if (loop_start[channel] < loop_end[channel]) - { - //Loop when the endpoint is reached. - loop_sync[channel] = BASS_ChannelSetSync( - m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, - loop_end[channel], loopProc, &loop_start[channel]); - } - else - { - //Loop when the end of the file is reached. - loop_sync[channel] = BASS_ChannelSetSync( - m_stream_list[channel], BASS_SYNC_END | BASS_SYNC_MIXTIME, - 0, loopProc, &loop_start[channel]); - } + if (loop_start[channel] < loop_end[channel]) + { + //Loop when the endpoint is reached. + loop_sync[channel] = BASS_ChannelSetSync( + m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, + loop_end[channel], loopProc, &loop_start[channel]); + } + else + { + //Loop when the end of the file is reached. + loop_sync[channel] = BASS_ChannelSetSync( + m_stream_list[channel], BASS_SYNC_END | BASS_SYNC_MIXTIME, + 0, loopProc, &loop_start[channel]); } } diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp deleted file mode 100644 index f8a8cfe3..00000000 --- a/src/aooptionsdialog.cpp +++ /dev/null @@ -1,1449 +0,0 @@ -#include "aooptionsdialog.h" -#include "aoapplication.h" -#include "courtroom.h" -#include "lobby.h" -#include "bass.h" -#include "networkmanager.h" - -#include <QFileDialog> - -AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) - : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint) -{ - ao_app = p_ao_app; - - // Setting up the basics. - setWindowFlag(Qt::WindowCloseButtonHint); - setWindowTitle(tr("Settings")); - resize(450, 408); - - ui_settings_buttons = new QDialogButtonBox(this); - - QSizePolicy sizePolicy1(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - sizePolicy1.setHorizontalStretch(0); - sizePolicy1.setVerticalStretch(0); - sizePolicy1.setHeightForWidth( - ui_settings_buttons->sizePolicy().hasHeightForWidth()); - ui_settings_buttons->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum)); - ui_settings_buttons->setOrientation(Qt::Horizontal); - ui_settings_buttons->setStandardButtons(QDialogButtonBox::Cancel | - QDialogButtonBox::Save | - QDialogButtonBox::RestoreDefaults); - - connect(ui_settings_buttons, &QDialogButtonBox::accepted, this, - &AOOptionsDialog::save_pressed); - connect(ui_settings_buttons, &QDialogButtonBox::rejected, this, - &AOOptionsDialog::discard_pressed); - connect(ui_settings_buttons, &QDialogButtonBox::clicked, this, - &AOOptionsDialog::button_clicked); - - // We'll stop updates so that the window won't flicker while it's being made. - setUpdatesEnabled(false); - - // 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_vertical_layout->addWidget(ui_settings_tabs); - ui_vertical_layout->addWidget(ui_settings_buttons); - - // Let's add the tabs one by one. - // First, we'll start with 'Gameplay'. - ui_gameplay_tab = new QWidget(this); - ui_gameplay_tab->setSizePolicy(sizePolicy1); - ui_settings_tabs->addTab(ui_gameplay_tab, tr("Gameplay")); - ui_form_layout_widget = new QWidget(ui_gameplay_tab); - ui_form_layout_widget->setSizePolicy(sizePolicy1); - - 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->setSpacing(4); - - int row = 0; - - 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(row, QFormLayout::LabelRole, ui_theme_label); - ui_theme_combobox = new QComboBox(ui_form_layout_widget); - - // Fill the combobox with the names of the themes. - QSet<QString> themes; - QStringList bases = ao_app->get_mount_paths(); - bases.push_front(ao_app->get_base_path()); - for (const QString &base : bases) { - QDirIterator it(base + "/themes", QDir::Dirs | QDir::NoDotAndDotDot, - QDirIterator::NoIteratorFlags); - while (it.hasNext()) { - QString actualname = QDir(it.next()).dirName(); - if (!themes.contains(actualname)) { - ui_theme_combobox->addItem(actualname); - themes.insert(actualname); - } - } - } - - connect(ui_theme_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, - &AOOptionsDialog::theme_changed); - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_theme_combobox); - - row += 1; - - ui_subtheme_label = new QLabel(ui_form_layout_widget); - ui_subtheme_label->setText(tr("Subtheme:")); - ui_subtheme_label->setToolTip( - tr("Sets a 'subtheme', which will stack on top of the current theme and replace anything it can." - "Keep it at 'server' to let the server decide. Keep it at 'default' to keep it unchanging.")); - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_subtheme_label); - ui_subtheme_combobox = new QComboBox(ui_form_layout_widget); - - // Fill the combobox with the names of the themes. - ui_subtheme_combobox->addItem("server"); - ui_subtheme_combobox->addItem("default"); - QDirIterator it2(ao_app->get_real_path(ao_app->get_theme_path("")), QDir::Dirs, - QDirIterator::NoIteratorFlags); - while (it2.hasNext()) { - QString actualname = QDir(it2.next()).dirName(); - if (actualname != "." && actualname != ".." && actualname.toLower() != "server" && actualname.toLower() != "default" && actualname.toLower() != "effects" && actualname.toLower() != "misc") { - ui_subtheme_combobox->addItem(actualname); - } - } - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_subtheme_combobox); - - row += 1; - ui_theme_reload_button = new QPushButton(ui_form_layout_widget); - ui_theme_reload_button->setText(tr("Reload Theme")); - ui_theme_reload_button->setToolTip( - tr("Refresh the theme and update all of the ui elements to match.")); - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_theme_reload_button); - connect(ui_theme_reload_button, &QPushButton::clicked, this, - &AOOptionsDialog::on_reload_theme_clicked); - - row += 1; - ui_theme_folder_button = new QPushButton(ui_form_layout_widget); - ui_theme_folder_button->setText(tr("Open Theme Folder")); - ui_theme_folder_button->setToolTip( - tr("Open the theme folder of the currently selected theme.")); - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_theme_folder_button); - connect(ui_theme_folder_button, &QPushButton::clicked, this, - [=] { - QString p_path = ao_app->get_real_path(ao_app->get_theme_path("", ui_theme_combobox->itemText(ui_theme_combobox->currentIndex()))); - if (!dir_exists(p_path)) { - return; - } - QDesktopServices::openUrl(QUrl::fromLocalFile(p_path)); - } - ); - - row += 1; - ui_animated_theme_lbl = new QLabel(ui_form_layout_widget); - ui_animated_theme_lbl->setText(tr("Animated Theme:")); - ui_animated_theme_lbl->setToolTip( - tr("If ticked, themes will be allowed to have animated elements.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_animated_theme_lbl); - - ui_animated_theme_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_animated_theme_cb); - - row += 1; - 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_gameplay_form->setWidget(row, QFormLayout::FieldRole, - ui_theme_log_divider); - - row += 1; - ui_stay_time_lbl = new QLabel(ui_form_layout_widget); - ui_stay_time_lbl->setText(tr("Text Stay Time:")); - ui_stay_time_lbl->setToolTip(tr( - "Minimum amount of time (in miliseconds) an IC message must stay on screen before " - "the next IC message is shown, acting as a 'queue'. Set to 0 to disable this behavior.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_stay_time_lbl); - - ui_stay_time_spinbox = new QSpinBox(ui_form_layout_widget); - ui_stay_time_spinbox->setSuffix(" ms"); - ui_stay_time_spinbox->setMaximum(10000); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_stay_time_spinbox); - - row += 1; - ui_instant_objection_lbl = new QLabel(ui_form_layout_widget); - ui_instant_objection_lbl->setText(tr("Instant Objection:")); - ui_instant_objection_lbl->setToolTip( - tr("If Text Stay Time is more than 0, instant objection will skip queued messages instead of waiting to catch up.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_instant_objection_lbl); - - ui_instant_objection_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_instant_objection_cb); - - row += 1; - ui_text_crawl_lbl = new QLabel(ui_form_layout_widget); - ui_text_crawl_lbl->setText(tr("Text crawl:")); - ui_text_crawl_lbl->setToolTip(tr( - "Amount of time (in miliseconds) spent on each letter when the in-character text is being displayed.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_text_crawl_lbl); - - ui_text_crawl_spinbox = new QSpinBox(ui_form_layout_widget); - ui_text_crawl_spinbox->setSuffix(" ms"); - ui_text_crawl_spinbox->setMaximum(500); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_text_crawl_spinbox); - - row += 1; - ui_chat_ratelimit_lbl = new QLabel(ui_form_layout_widget); - ui_chat_ratelimit_lbl->setText(tr("Chat Rate Limit:")); - ui_chat_ratelimit_lbl->setToolTip(tr( - "Minimum amount of time (in miliseconds) that must pass before the next Enter key press will send your IC message.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_chat_ratelimit_lbl); - - ui_chat_ratelimit_spinbox = new QSpinBox(ui_form_layout_widget); - ui_chat_ratelimit_spinbox->setSuffix(" ms"); - ui_chat_ratelimit_spinbox->setMaximum(5000); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_chat_ratelimit_spinbox); - - row += 1; - 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(row, QFormLayout::FieldRole, - ui_log_names_divider); - - row += 1; - 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(row, QFormLayout::LabelRole, ui_username_lbl); - - ui_username_textbox = new QLineEdit(ui_form_layout_widget); - ui_username_textbox->setMaxLength(30); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_username_textbox); - - row += 1; - 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(row, QFormLayout::LabelRole, ui_showname_lbl); - - ui_showname_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_showname_cb); - - row +=1; - ui_default_showname_lbl = new QLabel(ui_form_layout_widget); - ui_default_showname_lbl->setText(tr("Default showname:")); - ui_default_showname_lbl->setToolTip( - tr("Your showname will be automatically set to this value " - "when you join a server.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_default_showname_lbl); - - ui_default_showname_textbox = new QLineEdit(ui_form_layout_widget); - ui_default_showname_textbox->setMaxLength(30); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_default_showname_textbox); - - row += 1; - 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(row, QFormLayout::FieldRole, ui_net_divider); - - row += 1; - ui_ms_lbl = new QLabel(ui_form_layout_widget); - ui_ms_lbl->setText(tr("Alternate Server List:")); - ui_ms_lbl->setToolTip( - tr("Overrides the base URL to retrieve server information from.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_ms_lbl); - - ui_ms_textbox = new QLineEdit(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_ms_textbox); - - row += 1; - 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_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_discord_lbl); - - ui_discord_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_discord_cb); - - row += 1; - 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(row, QFormLayout::LabelRole, ui_language_label); - - ui_language_combobox = new QComboBox(ui_form_layout_widget); - ui_language_combobox->addItem( - ao_app->configini->value("language", " ").value<QString>() + - tr(" - 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("pl - Polskie"); - ui_language_combobox->addItem("jp - 日本語"); - ui_language_combobox->addItem("ru - Русский"); - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, - ui_language_combobox); - - row += 1; - ui_scaling_label = new QLabel(ui_form_layout_widget); - ui_scaling_label->setText(tr("Scaling:")); - ui_scaling_label->setToolTip( - tr("Sets the default scaling method, if there is not one already defined " - "specifically for the character.")); - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_scaling_label); - - ui_scaling_combobox = new QComboBox(ui_form_layout_widget); - // Corresponds with Qt::TransformationMode enum. Please don't change the order. - ui_scaling_combobox->addItem(tr("Pixel"), "fast"); - ui_scaling_combobox->addItem(tr("Smooth"), "smooth"); - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_scaling_combobox); - - row += 1; - ui_shake_lbl = new QLabel(ui_form_layout_widget); - ui_shake_lbl->setText(tr("Allow Screenshake:")); - ui_shake_lbl->setToolTip( - tr("Allows screenshaking. Disable this if you have concerns or issues " - "with photosensitivity and/or seizures.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_shake_lbl); - - ui_shake_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_shake_cb); - - row += 1; - ui_effects_lbl = new QLabel(ui_form_layout_widget); - ui_effects_lbl->setText(tr("Allow Effects:")); - ui_effects_lbl->setToolTip( - tr("Allows screen effects. Disable this if you have concerns or issues " - "with photosensitivity and/or seizures.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_effects_lbl); - - ui_effects_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_effects_cb); - - row += 1; - ui_framenetwork_lbl = new QLabel(ui_form_layout_widget); - ui_framenetwork_lbl->setText(tr("Network Frame Effects:")); - ui_framenetwork_lbl->setToolTip(tr( - "Send screen-shaking, flashes and sounds as defined in the char.ini over " - "the network. Only works for servers that support this functionality.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_framenetwork_lbl); - - ui_framenetwork_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_framenetwork_cb); - - row += 1; - ui_colorlog_lbl = new QLabel(ui_form_layout_widget); - ui_colorlog_lbl->setText(tr("Colors in IC Log:")); - ui_colorlog_lbl->setToolTip( - tr("Use the markup colors in the server IC chatlog.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_colorlog_lbl); - - ui_colorlog_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_colorlog_cb); - - row += 1; - ui_stickysounds_lbl = new QLabel(ui_form_layout_widget); - ui_stickysounds_lbl->setText(tr("Sticky Sounds:")); - ui_stickysounds_lbl->setToolTip( - tr("Turn this on to prevent the sound dropdown from clearing the sound " - "after playing it.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_stickysounds_lbl); - - ui_stickysounds_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_stickysounds_cb); - - row += 1; - ui_stickyeffects_lbl = new QLabel(ui_form_layout_widget); - ui_stickyeffects_lbl->setText(tr("Sticky Effects:")); - ui_stickyeffects_lbl->setToolTip( - tr("Turn this on to prevent the effects dropdown from clearing the " - "effect after playing it.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, - ui_stickyeffects_lbl); - - ui_stickyeffects_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_stickyeffects_cb); - - row += 1; - ui_stickypres_lbl = new QLabel(ui_form_layout_widget); - ui_stickypres_lbl->setText(tr("Sticky Preanims:")); - ui_stickypres_lbl->setToolTip( - tr("Turn this on to prevent preanimation checkbox from clearing after " - "playing the emote.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_stickypres_lbl); - - ui_stickypres_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_stickypres_cb); - - row += 1; - ui_customchat_lbl = new QLabel(ui_form_layout_widget); - ui_customchat_lbl->setText(tr("Custom Chatboxes:")); - ui_customchat_lbl->setToolTip( - tr("Turn this on to allow characters to define their own " - "custom chat box designs.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_customchat_lbl); - - ui_customchat_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_customchat_cb); - - row += 1; - ui_sticker_lbl = new QLabel(ui_form_layout_widget); - ui_sticker_lbl->setText(tr("Stickers:")); - ui_sticker_lbl->setToolTip( - tr("Turn this on to allow characters to define their own " - "stickers (unique images that show up over the chatbox - like avatars or shownames).")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_sticker_lbl); - - ui_sticker_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_sticker_cb); - - row += 1; - ui_continuous_lbl = new QLabel(ui_form_layout_widget); - ui_continuous_lbl->setText(tr("Continuous Playback:")); - ui_continuous_lbl->setToolTip( - tr("Whether or not to resume playing animations from where they left off. Turning off might reduce lag.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_continuous_lbl); - - ui_continuous_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_continuous_cb); - - row += 1; - ui_category_stop_lbl = new QLabel(ui_form_layout_widget); - ui_category_stop_lbl->setText(tr("Stop Music w/ Category:")); - ui_category_stop_lbl->setToolTip( - tr("Stop music when double-clicking a category. If this is disabled, use the right-click context menu to stop music.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_category_stop_lbl); - - ui_category_stop_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_category_stop_cb); - - row += 1; - - ui_sfx_on_idle_lbl = new QLabel(ui_form_layout_widget); - ui_sfx_on_idle_lbl->setText(tr("Always Send SFX:")); - ui_sfx_on_idle_lbl->setToolTip( - tr("If the SFX dropdown has an SFX selected, send the custom SFX alongside the message even if Preanim is OFF.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_sfx_on_idle_lbl); - - ui_sfx_on_idle_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_sfx_on_idle_cb); - - row += 1; - - ui_evidence_double_click_lbl = new QLabel(ui_form_layout_widget); - ui_evidence_double_click_lbl->setText(tr("Evidence Double Click:")); - ui_evidence_double_click_lbl->setToolTip( - tr("If ticked, Evidence needs a double-click to view rather than a single click.")); - - ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_evidence_double_click_lbl); - - ui_evidence_double_click_cb = new QCheckBox(ui_form_layout_widget); - - ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_evidence_double_click_cb); - - // Finish gameplay tab - QScrollArea *scroll = new QScrollArea(this); - scroll->setWidget(ui_form_layout_widget); - ui_gameplay_tab->setLayout(new QVBoxLayout); - ui_gameplay_tab->layout()->addWidget(scroll); - ui_gameplay_tab->show(); - - // Here we start the callwords tab. - ui_callwords_tab = new QWidget(this); - 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); - - 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("<html><head/><body>Enter as many callwords as you would like. These " - "are case insensitive. Make sure to leave every callword in its own " - "line!<br>Do not leave a line with a space at the end -- you will be " - "alerted everytime someone uses a space in their " - "messages.</body></html>")); - - ui_callwords_layout->addWidget(ui_callwords_explain_lbl); - - // The audio tab. - ui_audio_tab = new QWidget(this); - 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); - row = 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(row, 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 - int a = 0; - if (needs_default_audiodev()) { - - ui_audio_device_combobox->addItem("default"); //TODO translate this without breaking the default audio device - } - BASS_DEVICEINFO info; - for (a = 0; BASS_GetDeviceInfo(a, &info); a++) { - ui_audio_device_combobox->addItem(info.name); - if (ao_app->get_audio_output_device() == info.name) - ui_audio_device_combobox->setCurrentIndex( - ui_audio_device_combobox->count() - 1); - } - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, - ui_audio_device_combobox); - - row += 1; - 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(row, QFormLayout::FieldRole, - ui_audio_volume_divider); - - row += 1; - 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(row, QFormLayout::LabelRole, ui_music_volume_lbl); - - ui_music_volume_spinbox = new QSpinBox(ui_audio_widget); - ui_music_volume_spinbox->setMaximum(100); - ui_music_volume_spinbox->setSuffix("%"); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, - ui_music_volume_spinbox); - - row += 1; - 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(row, QFormLayout::LabelRole, ui_sfx_volume_lbl); - - ui_sfx_volume_spinbox = new QSpinBox(ui_audio_widget); - ui_sfx_volume_spinbox->setMaximum(100); - ui_sfx_volume_spinbox->setSuffix("%"); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, - ui_sfx_volume_spinbox); - - row += 1; - 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(row, QFormLayout::LabelRole, ui_blips_volume_lbl); - - ui_blips_volume_spinbox = new QSpinBox(ui_audio_widget); - ui_blips_volume_spinbox->setMaximum(100); - ui_blips_volume_spinbox->setSuffix("%"); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, - ui_blips_volume_spinbox); - - row += 1; - ui_suppress_audio_lbl = new QLabel(ui_audio_widget); - ui_suppress_audio_lbl->setText(tr("Suppress Audio:")); - ui_suppress_audio_lbl->setToolTip( - tr("How much of the volume to suppress when client is not in focus.")); - - ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_suppress_audio_lbl); - - ui_suppress_audio_spinbox = new QSpinBox(ui_audio_widget); - ui_suppress_audio_spinbox->setMaximum(100); - ui_suppress_audio_spinbox->setSuffix("%"); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, - ui_suppress_audio_spinbox); - - row += 1; - ui_volume_blip_divider = new QFrame(ui_audio_widget); - ui_volume_blip_divider->setFrameShape(QFrame::HLine); - ui_volume_blip_divider->setFrameShadow(QFrame::Sunken); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, - ui_volume_blip_divider); - - row += 1; - 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_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_bliprate_lbl); - - ui_bliprate_spinbox = new QSpinBox(ui_audio_widget); - ui_bliprate_spinbox->setMinimum(0); - ui_bliprate_spinbox->setToolTip( - tr("Play a blip sound \"once per every X symbols\", where " - "X is the blip rate. 0 plays a blip sound only once.")); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_bliprate_spinbox); - - row += 1; - 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_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_blank_blips_lbl); - - ui_blank_blips_cb = new QCheckBox(ui_audio_widget); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_blank_blips_cb); - - row += 1; - 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_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_loopsfx_lbl); - - ui_loopsfx_cb = new QCheckBox(ui_audio_widget); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_loopsfx_cb); - - row += 1; - ui_objectmusic_lbl = new QLabel(ui_audio_widget); - ui_objectmusic_lbl->setText(tr("Kill Music On Objection:")); - ui_objectmusic_lbl->setToolTip( - tr("If true, AO2 will ask the server to stop music when you use 'Objection!' ")); - - ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_objectmusic_lbl); - - ui_objectmusic_cb = new QCheckBox(ui_audio_widget); - - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_objectmusic_cb); - - row += 1; - ui_disablestreams_lbl = new QLabel(ui_audio_widget); - ui_disablestreams_lbl->setText(tr("Disable Music Streaming:")); - ui_disablestreams_lbl->setToolTip( - tr("If true, AO2 will not play any streamed audio and show that streaming is disabled.")); - ui_audio_layout->setWidget(row, QFormLayout::LabelRole, ui_disablestreams_lbl); - - ui_disablestreams_cb = new QCheckBox(ui_audio_widget); - ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_disablestreams_cb); - - // The casing tab! - ui_casing_tab = new QWidget(this); - ui_settings_tabs->addTab(ui_casing_tab, tr("Casing")); - - ui_casing_widget = new QWidget(ui_casing_tab); - ui_casing_widget->setGeometry(QRect(10, 10, 361, 211)); - - 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); - row = 0; - - // -- SERVER SUPPORTS CASING - - ui_casing_supported_lbl = new QLabel(ui_casing_widget); - if (ao_app->casing_alerts_supported) - 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_casing_layout->setWidget(row, QFormLayout::FieldRole, - ui_casing_supported_lbl); - - // -- CASE ANNOUNCEMENTS - - row += 1; - 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_casing_layout->setWidget(row, QFormLayout::LabelRole, - ui_casing_enabled_lbl); - - ui_casing_enabled_cb = new QCheckBox(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, - ui_casing_enabled_cb); - - // -- DEFENSE ANNOUNCEMENTS - - row += 1; - 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(row, QFormLayout::LabelRole, ui_casing_def_lbl); - - ui_casing_def_cb = new QCheckBox(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_def_cb); - - // -- PROSECUTOR ANNOUNCEMENTS - - row += 1; - 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(row, QFormLayout::LabelRole, ui_casing_pro_lbl); - - ui_casing_pro_cb = new QCheckBox(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_pro_cb); - - // -- JUDGE ANNOUNCEMENTS - - row += 1; - 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(row, QFormLayout::LabelRole, ui_casing_jud_lbl); - - ui_casing_jud_cb = new QCheckBox(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_jud_cb); - - // -- JUROR ANNOUNCEMENTS - - row += 1; - 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(row, QFormLayout::LabelRole, ui_casing_jur_lbl); - - ui_casing_jur_cb = new QCheckBox(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_jur_cb); - - // -- STENO ANNOUNCEMENTS - - row += 1; - 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(row, QFormLayout::LabelRole, ui_casing_steno_lbl); - - ui_casing_steno_cb = new QCheckBox(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_steno_cb); - - // -- CM ANNOUNCEMENTS - - row += 1; - 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(row, QFormLayout::LabelRole, ui_casing_cm_lbl); - - ui_casing_cm_cb = new QCheckBox(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_casing_cm_cb); - - // -- CM CASES ANNOUNCEMENTS - - row += 1; - 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(row, QFormLayout::LabelRole, - ui_casing_cm_cases_lbl); - - ui_casing_cm_cases_textbox = new QLineEdit(ui_casing_widget); - - ui_casing_layout->setWidget(row, QFormLayout::FieldRole, - ui_casing_cm_cases_textbox); - - // Assets tab - ui_assets_tab = new QWidget(this); - ui_assets_tab_layout = new QVBoxLayout(ui_assets_tab); - ui_assets_tab->setLayout(ui_assets_tab_layout); - ui_settings_tabs->addTab(ui_assets_tab, tr("Assets")); - - ui_asset_lbl = new QLabel(ui_assets_tab); - ui_asset_lbl->setText( - tr("Add or remove base folders for use by assets. " - "Base folders on the bottom are prioritized over those above them.")); - ui_asset_lbl->setWordWrap(true); - ui_assets_tab_layout->addWidget(ui_asset_lbl); - - ui_mount_list = new QListWidget(ui_assets_tab); - ui_assets_tab_layout->addWidget(ui_mount_list); - - ui_mount_buttons_layout = new QGridLayout(ui_assets_tab); - ui_assets_tab_layout->addLayout(ui_mount_buttons_layout); - - QSizePolicy stretch_btns(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); - stretch_btns.setHorizontalStretch(4); - - ui_mount_add = new QPushButton(tr("Add…"), ui_assets_tab); - ui_mount_add->setSizePolicy(stretch_btns); - ui_mount_buttons_layout->addWidget(ui_mount_add, 0, 0, 1, 1); - connect(ui_mount_add, &QPushButton::clicked, this, [this] { - QString path = QFileDialog::getExistingDirectory(this, tr("Select a base folder"), - QApplication::applicationDirPath(), - QFileDialog::ShowDirsOnly); - if (path.isEmpty()) { - return; - } - QDir dir(QApplication::applicationDirPath()); - QString relative = dir.relativeFilePath(path); - if (!relative.contains("../")) { - path = relative; - } - QListWidgetItem *dir_item = new QListWidgetItem(path); - ui_mount_list->addItem(dir_item); - ui_mount_list->setCurrentItem(dir_item); - - // quick hack to update buttons - emit ui_mount_list->itemSelectionChanged(); - }); - - ui_mount_remove = new QPushButton(tr("Remove"), ui_assets_tab); - ui_mount_remove->setSizePolicy(stretch_btns); - ui_mount_remove->setEnabled(false); - ui_mount_buttons_layout->addWidget(ui_mount_remove, 0, 1, 1, 1); - connect(ui_mount_remove, &QPushButton::clicked, this, [this] { - auto selected = ui_mount_list->selectedItems(); - if (selected.isEmpty()) - return; - delete selected[0]; - emit ui_mount_list->itemSelectionChanged(); - asset_cache_dirty = true; - }); - - auto *mount_buttons_spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, - QSizePolicy::Minimum); - ui_mount_buttons_layout->addItem(mount_buttons_spacer, 0, 2, 1, 1); - - ui_mount_up = new QPushButton(tr("↑"), ui_assets_tab); - ui_mount_up->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); - ui_mount_up->setMaximumWidth(40); - ui_mount_up->setEnabled(false); - ui_mount_buttons_layout->addWidget(ui_mount_up, 0, 3, 1, 1); - connect(ui_mount_up, &QPushButton::clicked, this, [this] { - auto selected = ui_mount_list->selectedItems(); - if (selected.isEmpty()) - return; - auto *item = selected[0]; - int row = ui_mount_list->row(item); - ui_mount_list->takeItem(row); - int new_row = qMax(1, row - 1); - ui_mount_list->insertItem(new_row, item); - ui_mount_list->setCurrentRow(new_row); - asset_cache_dirty = true; - }); - - ui_mount_down = new QPushButton(tr("↓"), ui_assets_tab); - ui_mount_down->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); - ui_mount_down->setMaximumWidth(40); - ui_mount_down->setEnabled(false); - ui_mount_buttons_layout->addWidget(ui_mount_down, 0, 4, 1, 1); - connect(ui_mount_down, &QPushButton::clicked, this, [this] { - auto selected = ui_mount_list->selectedItems(); - if (selected.isEmpty()) - return; - auto *item = selected[0]; - int row = ui_mount_list->row(item); - ui_mount_list->takeItem(row); - int new_row = qMin(ui_mount_list->count() + 1, row + 1); - ui_mount_list->insertItem(new_row, item); - ui_mount_list->setCurrentRow(new_row); - asset_cache_dirty = true; - }); - - auto *mount_buttons_spacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, - QSizePolicy::Minimum); - ui_mount_buttons_layout->addItem(mount_buttons_spacer_2, 0, 5, 1, 1); - - ui_mount_clear_cache = new QPushButton(tr("Clear Cache"), ui_assets_tab); - ui_mount_clear_cache->setToolTip(tr("Clears the lookup cache for assets. " - "Use this when you have added an asset that takes precedence over another " - "existing asset.")); - ui_mount_buttons_layout->addWidget(ui_mount_clear_cache, 0, 6, 1, 1); - connect(ui_mount_clear_cache, &QPushButton::clicked, this, [this] { - asset_cache_dirty = true; - ui_mount_clear_cache->setEnabled(false); - }); - - connect(ui_mount_list, &QListWidget::itemSelectionChanged, this, [this] { - auto selected_items = ui_mount_list->selectedItems(); - bool row_selected = !ui_mount_list->selectedItems().isEmpty(); - ui_mount_remove->setEnabled(row_selected); - ui_mount_up->setEnabled(row_selected); - ui_mount_down->setEnabled(row_selected); - - if (!row_selected) - return; - - int row = ui_mount_list->row(selected_items[0]); - if (row <= 1) - ui_mount_up->setEnabled(false); - if (row >= ui_mount_list->count() - 1) - ui_mount_down->setEnabled(false); - }); - - // Logging tab - ui_logging_tab = new QWidget(this); - ui_settings_tabs->addTab(ui_logging_tab, tr("Logging")); - ui_form_logging_widget = new QWidget(this); - - ui_logging_form = new QFormLayout(ui_form_logging_widget); - ui_logging_form->setLabelAlignment(Qt::AlignLeading | Qt::AlignLeft | - Qt::AlignVCenter); - ui_logging_form->setFormAlignment(Qt::AlignLeading | Qt::AlignLeft | - Qt::AlignTop); - ui_logging_form->setContentsMargins(5, 5, 0, 0); - ui_logging_form->setSpacing(4); - row = 0; - - ui_downwards_lbl = new QLabel(ui_form_logging_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_logging_form->setWidget(row, QFormLayout::LabelRole, ui_downwards_lbl); - - ui_downwards_cb = new QCheckBox(ui_form_logging_widget); - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_downwards_cb); - - row += 1; - ui_length_lbl = new QLabel(ui_form_logging_widget); - ui_length_lbl->setText(tr("Log length:")); - ui_length_lbl->setToolTip(tr( - "The amount of message lines the IC chatlog will keep before " - "deleting older message lines. A value of 0 or below counts as 'infinite'.")); - - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_length_lbl); - - ui_length_spinbox = new QSpinBox(ui_form_logging_widget); - ui_length_spinbox->setSuffix(" lines"); - ui_length_spinbox->setMaximum(10000); - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_length_spinbox); - - row += 1; - ui_log_newline_lbl = new QLabel(ui_form_logging_widget); - ui_log_newline_lbl->setText(tr("Log newline:")); - ui_log_newline_lbl->setToolTip( - tr("If ticked, new messages will appear separated, " - "with the message coming on the next line after the name. " - "When unticked, it displays it as 'name: message'.")); - - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_log_newline_lbl); - - ui_log_newline_cb = new QCheckBox(ui_form_logging_widget); - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_log_newline_cb); - - row += 1; - ui_log_margin_lbl = new QLabel(ui_form_logging_widget); - ui_log_margin_lbl->setText(tr("Log margin:")); - ui_log_margin_lbl->setToolTip(tr( - "The distance in pixels between each entry in the IC log. " - "Default: 0.")); - - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_log_margin_lbl); - - ui_log_margin_spinbox = new QSpinBox(ui_form_logging_widget); - ui_log_margin_spinbox->setSuffix(" px"); - ui_log_margin_spinbox->setMaximum(1000); - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_log_margin_spinbox); - - row += 1; - ui_log_timestamp_lbl = new QLabel(ui_form_logging_widget); - ui_log_timestamp_lbl->setText(tr("Log timestamp:")); - ui_log_timestamp_lbl->setToolTip( - tr("If ticked, log will contain a timestamp in UTC before the name.")); - - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_log_timestamp_lbl); - - ui_log_timestamp_cb = new QCheckBox(ui_form_logging_widget); - - connect(ui_log_timestamp_cb, &QCheckBox::stateChanged, this, &AOOptionsDialog::timestamp_cb_changed); - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_log_timestamp_cb); - - row += 1; - ui_log_timestamp_format_lbl = new QLabel(ui_form_logging_widget); - ui_log_timestamp_format_lbl->setText(tr("Log timestamp format:\n") + QDateTime::currentDateTime().toString(ao_app->get_log_timestamp_format())); - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_log_timestamp_format_lbl); - - ui_log_timestamp_format_combobox = new QComboBox(ui_form_logging_widget); - ui_log_timestamp_format_combobox->setEditable(true); - - QString l_current_format = ao_app->get_log_timestamp_format(); - - ui_log_timestamp_format_combobox->setCurrentText(l_current_format); - ui_log_timestamp_format_combobox->addItem("h:mm:ss AP"); // 2:13:09 PM - ui_log_timestamp_format_combobox->addItem("hh:mm:ss"); // 14:13:09 - ui_log_timestamp_format_combobox->addItem("h:mm AP"); // 2:13 PM - ui_log_timestamp_format_combobox->addItem("hh:mm"); // 14:13 - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_log_timestamp_format_combobox); - - connect(ui_log_timestamp_format_combobox, &QComboBox::currentTextChanged, this, &AOOptionsDialog::on_timestamp_format_edited); - - if(!ao_app->get_log_timestamp()) { - ui_log_timestamp_format_combobox->setDisabled(true); - } - row += 1; - ui_log_ic_actions_lbl = new QLabel(ui_form_logging_widget); - ui_log_ic_actions_lbl->setText(tr("Log IC actions:")); - ui_log_ic_actions_lbl->setToolTip( - tr("If ticked, log will show IC actions such as shouting and presenting evidence.")); - - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_log_ic_actions_lbl); - - ui_log_ic_actions_cb = new QCheckBox(ui_form_logging_widget); - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_log_ic_actions_cb); - - row += 1; - ui_desync_logs_lbl = new QLabel(ui_form_logging_widget); - ui_desync_logs_lbl->setText(tr("Desynchronize IC Logs:")); - ui_desync_logs_lbl->setToolTip( - tr("If ticked, log will show messages as-received, while viewport will parse according to the queue (Text Stay Time).")); - - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_desync_logs_lbl); - - ui_desync_logs_cb = new QCheckBox(ui_form_logging_widget); - - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_desync_logs_cb); - - //Check whether mass logging is enabled - row += 1; - ui_log_text_lbl = new QLabel(ui_form_logging_widget); - ui_log_text_lbl->setText(tr("Log to Text Files:")); - ui_log_text_lbl->setToolTip( - tr("Text logs of gameplay will be automatically written in the /logs folder.")); - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_log_text_lbl); - - ui_log_text_cb = new QCheckBox(ui_form_logging_widget); - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_log_text_cb); - - row += 1; - ui_log_demo_lbl = new QLabel(ui_form_logging_widget); - ui_log_demo_lbl->setText(tr("Log to Demo Files:")); - ui_log_demo_lbl->setToolTip( - tr("Gameplay will be automatically recorded as demos in the /logs folder.")); - ui_logging_form->setWidget(row, QFormLayout::LabelRole, ui_log_demo_lbl); - - ui_log_demo_cb = new QCheckBox(ui_form_logging_widget); - ui_logging_form->setWidget(row, QFormLayout::FieldRole, ui_log_demo_cb); - - // Finish logging tab - QScrollArea *log_scroll = new QScrollArea(this); - log_scroll->setWidget(ui_form_logging_widget); - ui_logging_tab->setLayout(new QVBoxLayout); - ui_logging_tab->layout()->addWidget(log_scroll); - - // Privacy tab - ui_privacy_tab = new QWidget(this); - ui_settings_tabs->addTab(ui_privacy_tab, tr("Privacy")); - - ui_privacy_layout = new QVBoxLayout(ui_privacy_tab); - - ui_privacy_optout_cb = new QCheckBox(ui_privacy_tab); - ui_privacy_optout_cb->setText(tr("Do not include me in public player counts")); - ui_privacy_layout->addWidget(ui_privacy_optout_cb); - - ui_privacy_separator = new QFrame(ui_privacy_tab); - ui_privacy_separator->setObjectName(QString::fromUtf8("line")); - ui_privacy_separator->setFrameShape(QFrame::HLine); - ui_privacy_separator->setFrameShadow(QFrame::Sunken); - ui_privacy_layout->addWidget(ui_privacy_separator); - - ui_privacy_policy = new QTextBrowser(ui_privacy_tab); - QSizePolicy privacySizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - sizePolicy.setHorizontalStretch(0); - sizePolicy.setVerticalStretch(0); - ui_privacy_policy->setSizePolicy(privacySizePolicy); - ui_privacy_policy->setPlainText(tr("Getting privacy policy...")); - ui_privacy_layout->addWidget(ui_privacy_policy); - - update_values(); - - // When we're done, we should continue the updates! - setUpdatesEnabled(true); -} - -void AOOptionsDialog::update_values() { - for (int i = 0; i < ui_theme_combobox->count(); ++i) { - if (ui_theme_combobox->itemText(i) == ao_app->read_theme()) - { - ui_theme_combobox->setCurrentIndex(i); - break; - } - } - QString subtheme = - ao_app->configini->value("subtheme").value<QString>(); - for (int i = 0; i < ui_subtheme_combobox->count(); ++i) { - if (ui_subtheme_combobox->itemText(i) == subtheme) - { - ui_subtheme_combobox->setCurrentIndex(i); - break; - } - } - Qt::TransformationMode scaling = ao_app->get_scaling(ao_app->get_default_scaling()); - ui_scaling_combobox->setCurrentIndex(scaling); - - // Let's fill the callwords text edit with the already present callwords. - ui_callwords_textbox->document()->clear(); - foreach (QString callword, ao_app->get_call_words()) { - ui_callwords_textbox->appendPlainText(callword); - } - ui_animated_theme_cb->setChecked(ao_app->get_animated_theme()); - ui_ms_textbox->setText(ao_app->configini->value("master", "").value<QString>()); - ui_casing_cm_cases_textbox->setText(ao_app->get_casing_can_host_cases()); - ui_username_textbox->setText(ao_app->get_default_username()); - ui_downwards_cb->setChecked(ao_app->get_log_goes_downwards()); - ui_log_newline_cb->setChecked(ao_app->get_log_newline()); - ui_log_timestamp_cb->setChecked(ao_app->get_log_timestamp()); - ui_log_timestamp_format_combobox->setCurrentText(ao_app->get_log_timestamp_format()); - ui_log_ic_actions_cb->setChecked(ao_app->get_log_ic_actions()); - ui_desync_logs_cb->setChecked(ao_app->is_desyncrhonized_logs_enabled()); - ui_instant_objection_cb->setChecked(ao_app->is_instant_objection_enabled()); - ui_showname_cb->setChecked(ao_app->get_showname_enabled_by_default()); - ui_discord_cb->setChecked(ao_app->is_discord_enabled()); - ui_shake_cb->setChecked(ao_app->is_shake_enabled()); - ui_effects_cb->setChecked(ao_app->is_effects_enabled()); - ui_framenetwork_cb->setChecked(ao_app->is_frame_network_enabled()); - ui_colorlog_cb->setChecked(ao_app->is_colorlog_enabled()); - ui_stickysounds_cb->setChecked(ao_app->is_stickysounds_enabled()); - ui_stickyeffects_cb->setChecked(ao_app->is_stickyeffects_enabled()); - ui_stickypres_cb->setChecked(ao_app->is_stickypres_enabled()); - ui_customchat_cb->setChecked(ao_app->is_customchat_enabled()); - ui_sticker_cb->setChecked(ao_app->is_sticker_enabled()); - ui_continuous_cb->setChecked(ao_app->is_continuous_enabled()); - ui_category_stop_cb->setChecked(ao_app->is_category_stop_enabled()); - ui_sfx_on_idle_cb->setChecked(ao_app->get_sfx_on_idle()); - ui_blank_blips_cb->setChecked(ao_app->get_blank_blip()); - ui_loopsfx_cb->setChecked(ao_app->get_looping_sfx()); - ui_objectmusic_cb->setChecked(ao_app->objection_stop_music()); - ui_disablestreams_cb->setChecked(ao_app->is_streaming_disabled()); - ui_casing_enabled_cb->setChecked(ao_app->get_casing_enabled()); - ui_casing_def_cb->setChecked(ao_app->get_casing_defence_enabled()); - ui_casing_pro_cb->setChecked(ao_app->get_casing_prosecution_enabled()); - ui_casing_jud_cb->setChecked(ao_app->get_casing_judge_enabled()); - ui_casing_jur_cb->setChecked(ao_app->get_casing_juror_enabled()); - ui_casing_steno_cb->setChecked(ao_app->get_casing_steno_enabled()); - ui_casing_cm_cb->setChecked(ao_app->get_casing_cm_enabled()); - ui_log_text_cb->setChecked(ao_app->get_text_logging_enabled()); - ui_log_demo_cb->setChecked(ao_app->get_demo_logging_enabled()); - ui_length_spinbox->setValue(ao_app->get_max_log_size()); - ui_log_margin_spinbox->setValue(ao_app->get_log_margin()); - ui_stay_time_spinbox->setValue(ao_app->stay_time()); - ui_text_crawl_spinbox->setValue(ao_app->get_text_crawl()); - ui_chat_ratelimit_spinbox->setValue(ao_app->get_chat_ratelimit()); - ui_music_volume_spinbox->setValue(ao_app->get_default_music()); - ui_sfx_volume_spinbox->setValue(ao_app->get_default_sfx()); - ui_blips_volume_spinbox->setValue(ao_app->get_default_blip()); - ui_suppress_audio_spinbox->setValue(ao_app->get_default_suppress_audio()); - ui_bliprate_spinbox->setValue(ao_app->read_blip_rate()); - ui_default_showname_textbox->setText(ao_app->get_default_showname()); - ui_evidence_double_click_cb->setChecked(ao_app->get_evidence_double_click()); - - auto *defaultMount = new QListWidgetItem(tr("%1 (default)") - .arg(ao_app->get_base_path())); - defaultMount->setFlags(Qt::ItemFlag::NoItemFlags); - - //Clear the list to prevent duplication of default entries. - ui_mount_list->clear(); - ui_mount_list->addItem(defaultMount); - ui_mount_list->addItems(ao_app->get_mount_paths()); - - ui_privacy_optout_cb->setChecked(ao_app->get_player_count_optout()); - - ao_app->net_manager->request_document(MSDocumentType::PrivacyPolicy, [this](QString document) { - if (document.isEmpty()) { - document = tr("Couldn't get the privacy policy."); - } - ui_privacy_policy->setHtml(document); - }); -} - -void AOOptionsDialog::save_pressed() -{ - // Save everything into the config.ini. - QSettings *configini = ao_app->configini; - - const bool audioChanged = ui_audio_device_combobox->currentText() != - ao_app->get_audio_output_device(); - - configini->setValue("theme", ui_theme_combobox->currentText()); - configini->setValue("subtheme", ui_subtheme_combobox->currentText()); - configini->setValue("animated_theme", ui_animated_theme_cb->isChecked()); - configini->setValue("log_goes_downwards", ui_downwards_cb->isChecked()); - configini->setValue("log_maximum", ui_length_spinbox->value()); - configini->setValue("log_newline", ui_log_newline_cb->isChecked()); - configini->setValue("log_margin", ui_log_margin_spinbox->value()); - configini->setValue("log_timestamp", ui_log_timestamp_cb->isChecked()); - configini->setValue("log_timestamp_format", ui_log_timestamp_format_combobox->currentText()); - configini->setValue("log_ic_actions", ui_log_ic_actions_cb->isChecked()); - configini->setValue("desync_logs", ui_desync_logs_cb->isChecked()); - configini->setValue("stay_time", ui_stay_time_spinbox->value()); - configini->setValue("instant_objection", ui_instant_objection_cb->isChecked()); - configini->setValue("text_crawl", ui_text_crawl_spinbox->value()); - configini->setValue("chat_ratelimit", ui_chat_ratelimit_spinbox->value()); - configini->setValue("default_username", ui_username_textbox->text()); - configini->setValue("show_custom_shownames", ui_showname_cb->isChecked()); - configini->setValue("default_showname", ui_default_showname_textbox->text()); - configini->setValue("master", ui_ms_textbox->text()); - configini->setValue("discord", ui_discord_cb->isChecked()); - configini->setValue("language", ui_language_combobox->currentText().left(2)); - configini->setValue("default_scaling", ui_scaling_combobox->currentData()); - configini->setValue("shake", ui_shake_cb->isChecked()); - configini->setValue("effects", ui_effects_cb->isChecked()); - configini->setValue("framenetwork", ui_framenetwork_cb->isChecked()); - configini->setValue("colorlog", ui_colorlog_cb->isChecked()); - configini->setValue("stickysounds", ui_stickysounds_cb->isChecked()); - configini->setValue("stickyeffects", ui_stickyeffects_cb->isChecked()); - configini->setValue("stickypres", ui_stickypres_cb->isChecked()); - configini->setValue("customchat", ui_customchat_cb->isChecked()); - configini->setValue("sticker", ui_sticker_cb->isChecked()); - configini->setValue("automatic_logging_enabled", ui_log_text_cb->isChecked()); - configini->setValue("demo_logging_enabled", ui_log_demo_cb->isChecked()); - configini->setValue("continuous_playback", ui_continuous_cb->isChecked()); - configini->setValue("category_stop", ui_category_stop_cb->isChecked()); - configini->setValue("sfx_on_idle", ui_sfx_on_idle_cb->isChecked()); - configini->setValue("evidence_double_click", ui_evidence_double_click_cb->isChecked()); - QFile *callwordsini = new QFile(ao_app->get_base_path() + "callwords.ini"); - - if (callwordsini->open(QIODevice::WriteOnly | QIODevice::Truncate | - QIODevice::Text)) { - QTextStream out(callwordsini); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - out.setCodec("UTF-8"); -#endif - 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("suppress_audio", ui_suppress_audio_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("objection_stop_music", ui_objectmusic_cb->isChecked()); - configini->setValue("streaming_disabled", ui_disablestreams_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_can_host_cases", - ui_casing_cm_cases_textbox->text()); - configini->setValue("player_count_optout", ui_privacy_optout_cb->isChecked()); - - QStringList mountPaths; - for (int i = 1; i < ui_mount_list->count(); i++) - mountPaths.append(ui_mount_list->item(i)->text()); - configini->setValue("mount_paths", mountPaths); - - if (audioChanged) - ao_app->initBASS(); - - if (asset_cache_dirty) - ao_app->invalidate_lookup_cache(); - - // We most probably pressed "Restore defaults" at some point. Since we're saving our settings, remove the temporary file. - if (QFile::exists(ao_app->get_base_path() + "config.temp")) - QFile::remove(ao_app->get_base_path() + "config.temp"); - done(0); -} - -void AOOptionsDialog::discard_pressed() { - // The .temp file exists, meaning we are trying to undo the user clicking on "Restore defaults" and bring back the old settings. - if (QFile::exists(ao_app->get_base_path() + "config.temp")) { - // Delete the QSettings object so it does not interfere with the file - delete ao_app->configini; - // Remove the current config.ini - QFile::remove(ao_app->get_base_path() + "config.ini"); - // Rename .temp to .ini - QFile::rename(ao_app->get_base_path() + "config.temp", ao_app->get_base_path() + "config.ini"); - // Recreate the QSettings object from the ini file, restoring the settings before the Options Dialog was opened.. - ao_app->configini = - new QSettings(ao_app->get_base_path() + "config.ini", QSettings::IniFormat); - } - done(0); -} - -void AOOptionsDialog::button_clicked(QAbstractButton *button) { - if (ui_settings_buttons->buttonRole(button) == QDialogButtonBox::ResetRole) { - // Store the current settings as a .temp file - QFile::rename(ao_app->get_base_path() + "config.ini", ao_app->get_base_path() + "config.temp"); - // Load up the default settings - ao_app->configini->clear(); - // Update the values on the settings ui - update_values(); - } -} - -void AOOptionsDialog::on_reload_theme_clicked() { - ao_app->configini->setValue("theme", ui_theme_combobox->currentText()); - ao_app->configini->setValue("subtheme", ui_subtheme_combobox->currentText()); - ao_app->configini->setValue("animated_theme", ui_animated_theme_cb->isChecked()); - if (ao_app->courtroom_constructed) - ao_app->w_courtroom->on_reload_theme_clicked(); - if (ao_app->lobby_constructed) - ao_app->w_lobby->set_widgets(); -} - -void AOOptionsDialog::theme_changed(int i) { - ui_subtheme_combobox->clear(); - // Fill the combobox with the names of the themes. - ui_subtheme_combobox->addItem("server"); - ui_subtheme_combobox->addItem("default"); - QDirIterator it(ao_app->get_real_path(ao_app->get_theme_path("", ui_theme_combobox->itemText(i))), QDir::Dirs, - QDirIterator::NoIteratorFlags); - while (it.hasNext()) { - QString actualname = QDir(it.next()).dirName(); - if (actualname != "." && actualname != ".." && actualname.toLower() != "server" && actualname.toLower() != "default" && actualname.toLower() != "effects" && actualname.toLower() != "misc") - ui_subtheme_combobox->addItem(actualname); - } - -} - -void AOOptionsDialog::on_timestamp_format_edited() { ui_log_timestamp_format_lbl->setText(tr("Log timestamp format:\n") + QDateTime::currentDateTime().toString(ui_log_timestamp_format_combobox->currentText())); } - -void AOOptionsDialog::timestamp_cb_changed(int state) { ui_log_timestamp_format_combobox->setDisabled(state == 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; } -#elif defined __APPLE__ -bool AOOptionsDialog::needs_default_audiodev() { return true; } -#else -#error This operating system is not supported. -#endif diff --git a/src/charselect.cpp b/src/charselect.cpp index a9770048..7a3ec1a1 100644 --- a/src/charselect.cpp +++ b/src/charselect.cpp @@ -98,8 +98,14 @@ void Courtroom::set_char_select() set_size_and_pos(ui_char_taken, "char_taken"); set_size_and_pos(ui_char_buttons, "char_buttons"); + // Silence emission. This causes the signal to be emitted TWICE during server join! + // Fuck this. Performance Sandwich. + ui_char_taken->blockSignals(true); + ui_char_passworded->blockSignals(true); ui_char_taken->setChecked(true); ui_char_passworded->setChecked(true); + ui_char_taken->blockSignals(false); + ui_char_passworded->blockSignals(false); truncate_label_text(ui_char_taken, "char_taken"); truncate_label_text(ui_char_passworded, "char_passworded"); @@ -142,6 +148,18 @@ void Courtroom::set_char_select_page() if (current_char_page > 0) ui_char_select_left->show(); + QPoint f_spacing = + ao_app->get_button_spacing("char_button_spacing", "courtroom_design.ini"); + + char_columns = + ((ui_char_buttons->width() - button_width) / (f_spacing.x() + button_width)) + + 1; + char_rows = ((ui_char_buttons->height() - button_height) / + (f_spacing.y() + button_height)) + + 1; + + max_chars_on_page = char_columns * char_rows; + put_button_in_place(current_char_page * max_chars_on_page, chars_on_page); } @@ -233,25 +251,13 @@ void Courtroom::put_button_in_place(int starting, int chars_on_this_page) QPoint f_spacing = ao_app->get_button_spacing("char_button_spacing", "courtroom_design.ini"); - int x_spacing = f_spacing.x(); int x_mod_count = 0; - - int y_spacing = f_spacing.y(); int y_mod_count = 0; - char_columns = - ((ui_char_buttons->width() - button_width) / (x_spacing + button_width)) + - 1; - char_rows = ((ui_char_buttons->height() - button_height) / - (y_spacing + button_height)) + - 1; - - max_chars_on_page = char_columns * char_rows; - int startout = starting; for (int n = starting; n < startout + chars_on_this_page; ++n) { - int x_pos = (button_width + x_spacing) * x_mod_count; - int y_pos = (button_height + y_spacing) * y_mod_count; + int x_pos = (button_width + f_spacing.x()) * x_mod_count; + int y_pos = (button_height + f_spacing.y()) * y_mod_count; ui_char_button_list_filtered.at(n)->move(x_pos, y_pos); ui_char_button_list_filtered.at(n)->show(); @@ -324,19 +330,6 @@ void Courtroom::character_loading_finished() // still running, it is just loading the pictures of the characters. if (ao_app->lobby_constructed) { ao_app->generated_chars++; - int total_loading_size = ao_app->char_list_size * 2 + - ao_app->evidence_list_size + - ao_app->music_list_size; - int loading_value = - int(((ao_app->loaded_chars + ao_app->generated_chars + - ao_app->loaded_music + ao_app->loaded_evidence) / - static_cast<double>(total_loading_size)) * - 100); - ao_app->w_lobby->set_loading_value(loading_value); - ao_app->w_lobby->set_loading_text( - tr("Generating chars:\n%1/%2").arg( - QString::number(ao_app->generated_chars), - QString::number(ao_app->char_list_size))); } } ui_char_list->expandAll(); diff --git a/src/courtroom.cpp b/src/courtroom.cpp index a08b5e13..65c5e1a3 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1,4 +1,5 @@ #include "courtroom.h" +#include "options.h" Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() { @@ -52,6 +53,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_vp_background->setObjectName("ui_vp_background"); ui_vp_speedlines = new SplashLayer(ui_viewport, ao_app); ui_vp_speedlines->setObjectName("ui_vp_speedlines"); + ui_vp_speedlines->stretch = true; ui_vp_player_char = new CharLayer(ui_viewport, ao_app); ui_vp_player_char->setObjectName("ui_vp_player_char"); ui_vp_player_char->masked = false; @@ -114,15 +116,15 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_ic_chatlog->setReadOnly(true); ui_ic_chatlog->setObjectName("ui_ic_chatlog"); - log_maximum_blocks = ao_app->get_max_log_size(); - log_goes_downwards = ao_app->get_log_goes_downwards(); - log_colors = ao_app->is_colorlog_enabled(); - log_newline = ao_app->get_log_newline(); - log_margin = ao_app->get_log_margin(); - log_timestamp = ao_app->get_log_timestamp(); - log_timestamp_format = ao_app->get_log_timestamp_format(); + log_maximum_blocks = Options::getInstance().maxLogSize(); + log_goes_downwards = Options::getInstance().logDirectionDownwards(); + log_colors = Options::getInstance().colorLogEnabled(); + log_newline = Options::getInstance().logNewline(); + log_margin = Options::getInstance().logMargin(); + log_timestamp = Options::getInstance().logTimestampEnabled(); + log_timestamp_format = Options::getInstance().logTimestampFormat(); - ui_debug_log = new AOTextArea(this, ao_app->get_max_log_size()); + ui_debug_log = new AOTextArea(this, Options::getInstance().maxLogSize()); ui_debug_log->setReadOnly(true); ui_debug_log->setOpenExternalLinks(true); ui_debug_log->hide(); @@ -176,7 +178,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_ic_chat_name = new QLineEdit(this); ui_ic_chat_name->setFrame(false); ui_ic_chat_name->setPlaceholderText(tr("Showname")); - ui_ic_chat_name->setText(p_ao_app->get_default_showname()); + ui_ic_chat_name->setText(Options::getInstance().shownameOnJoin()); ui_ic_chat_name->setObjectName("ui_ic_chat_name"); ui_ic_chat_message = new QLineEdit(this); @@ -200,7 +202,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_ooc_chat_name->setFrame(false); ui_ooc_chat_name->setPlaceholderText(tr("Name")); ui_ooc_chat_name->setMaxLength(30); - ui_ooc_chat_name->setText(p_ao_app->get_default_username()); + ui_ooc_chat_name->setText(Options::getInstance().username()); ui_ooc_chat_name->setObjectName("ui_ooc_chat_name"); // ui_area_password = new QLineEdit(this); @@ -290,9 +292,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_settings = new AOButton(this, ao_app); ui_settings->setObjectName("ui_settings"); - ui_announce_casing = new AOButton(this, ao_app); - ui_announce_casing->setObjectName("ui_announce_casing"); - ui_switch_area_music = new AOButton(this, ao_app); ui_switch_area_music->setObjectName("ui_switch_area_music"); @@ -315,14 +314,8 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_additive->hide(); ui_additive->setObjectName("ui_additive"); - ui_casing = new QCheckBox(this); - ui_casing->setChecked(ao_app->get_casing_enabled()); - ui_casing->setText(tr("Casing")); - ui_casing->hide(); - ui_casing->setObjectName("ui_casing"); - ui_showname_enable = new QCheckBox(this); - ui_showname_enable->setChecked(ao_app->get_showname_enabled_by_default()); + ui_showname_enable->setChecked(Options::getInstance().customShownameEnabled()); ui_showname_enable->setText(tr("Shownames")); ui_showname_enable->setObjectName("ui_showname_enable"); @@ -365,17 +358,17 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_music_slider = new QSlider(Qt::Horizontal, this); ui_music_slider->setRange(0, 100); - ui_music_slider->setValue(ao_app->get_default_music()); + ui_music_slider->setValue(Options::getInstance().musicVolume()); ui_music_slider->setObjectName("ui_music_slider"); ui_sfx_slider = new QSlider(Qt::Horizontal, this); ui_sfx_slider->setRange(0, 100); - ui_sfx_slider->setValue(ao_app->get_default_sfx()); + ui_sfx_slider->setValue(Options::getInstance().sfxVolume()); ui_sfx_slider->setObjectName("ui_sfx_slider"); ui_blip_slider = new QSlider(Qt::Horizontal, this); ui_blip_slider->setRange(0, 100); - ui_blip_slider->setValue(ao_app->get_default_blip()); + ui_blip_slider->setValue(Options::getInstance().blipVolume()); ui_blip_slider->setObjectName("ui_blip_slider"); ui_mute_list = new QListWidget(this); @@ -539,8 +532,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() &Courtroom::on_reload_theme_clicked); connect(ui_call_mod, &AOButton::clicked, this, &Courtroom::on_call_mod_clicked); connect(ui_settings, &AOButton::clicked, this, &Courtroom::on_settings_clicked); - connect(ui_announce_casing, &AOButton::clicked, this, - &Courtroom::on_announce_casing_clicked); connect(ui_switch_area_music, &AOButton::clicked, this, &Courtroom::on_switch_area_music_clicked); @@ -548,7 +539,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() connect(ui_flip, &AOButton::clicked, this, &Courtroom::on_flip_clicked); connect(ui_additive, &AOButton::clicked, this, &Courtroom::on_additive_clicked); connect(ui_guard, &AOButton::clicked, this, &Courtroom::on_guard_clicked); - connect(ui_casing, &AOButton::clicked, this, &Courtroom::on_casing_clicked); connect(ui_showname_enable, &AOButton::clicked, this, &Courtroom::on_showname_enable_clicked); @@ -584,7 +574,7 @@ void Courtroom::on_application_state_changed(Qt::ApplicationState state) suppress_audio = 0; if (state != Qt::ApplicationActive) { // Suppressed audio setting - suppress_audio = ao_app->get_default_suppress_audio(); + suppress_audio = Options::getInstance().defaultSuppressAudio(); } update_audio_volume(); } @@ -668,9 +658,6 @@ void Courtroom::set_pair_list() void Courtroom::set_widgets() { QString filename = "courtroom_design.ini"; - // Update the default theme from the courtroom_design.ini, if it's not defined it will be 'default'. - QSettings settings(ao_app->get_real_path(ao_app->get_theme_path(filename, ao_app->current_theme)), QSettings::IniFormat); - ao_app->default_theme = settings.value("default_theme", "default").toString(); set_fonts(); set_size_and_pos(ui_viewport, "viewport"); @@ -693,15 +680,6 @@ void Courtroom::set_widgets() ui_ic_chat_name->setEnabled(false); } - if (ao_app->casing_alerts_supported) { - ui_announce_casing->show(); - ui_casing->show(); - } - else { - ui_announce_casing->hide(); - ui_casing->hide(); - } - // We also show the non-server-dependent client additions. // Once again, if the theme can't display it, set_move_and_pos will catch // them. @@ -748,20 +726,20 @@ void Courtroom::set_widgets() ui_vp_objection->move_and_center(ui_viewport->x(), ui_viewport->y()); ui_vp_objection->combo_resize(ui_viewport->width(), ui_viewport->height()); - log_maximum_blocks = ao_app->get_max_log_size(); - - bool regenerate = log_goes_downwards != ao_app->get_log_goes_downwards() || - log_colors != ao_app->is_colorlog_enabled() || - log_newline != ao_app->get_log_newline() || - log_margin != ao_app->get_log_margin() || - log_timestamp != ao_app->get_log_timestamp() || - log_timestamp_format != ao_app->get_log_timestamp_format(); - log_goes_downwards = ao_app->get_log_goes_downwards(); - log_colors = ao_app->is_colorlog_enabled(); - log_newline = ao_app->get_log_newline(); - log_margin = ao_app->get_log_margin(); - log_timestamp = ao_app->get_log_timestamp(); - log_timestamp_format = ao_app->get_log_timestamp_format(); + log_maximum_blocks = Options::getInstance().maxLogSize(); + + bool regenerate = log_goes_downwards != Options::getInstance().logDirectionDownwards() || + log_colors != Options::getInstance().colorLogEnabled() || + log_newline != Options::getInstance().logNewline() || + log_margin != Options::getInstance().logMargin() || + log_timestamp != Options::getInstance().logTimestampEnabled() || + log_timestamp_format != Options::getInstance().logTimestampFormat(); + log_goes_downwards = Options::getInstance().logDirectionDownwards(); + log_colors = Options::getInstance().colorLogEnabled(); + log_newline = Options::getInstance().logNewline(); + log_margin = Options::getInstance().logMargin(); + log_timestamp = Options::getInstance().logTimestampEnabled(); + log_timestamp_format = Options::getInstance().logTimestampFormat(); if (regenerate) { regenerate_ic_chatlog(); } @@ -1014,13 +992,6 @@ void Courtroom::set_widgets() ui_settings->setToolTip( tr("Allows you to change various aspects of the client.")); - set_size_and_pos(ui_announce_casing, "casing_button"); - ui_announce_casing->setText(tr("Casing")); - ui_announce_casing->set_image("casing_button"); - ui_announce_casing->setToolTip( - tr("An interface to help you announce a case (you have to be a CM first " - "to be able to announce cases)")); - set_size_and_pos(ui_switch_area_music, "switch_area_music"); ui_switch_area_music->setText(tr("A/M")); ui_switch_area_music->set_image("switch_area_music"); @@ -1061,10 +1032,6 @@ void Courtroom::set_widgets() tr("Do not listen to mod calls when checked, preventing them from " "playing sounds or focusing attention on the window.")); - set_size_and_pos(ui_casing, "casing"); - ui_casing->setToolTip(tr("Lets you receive case alerts when enabled.\n" - "(You can set your preferences in the Settings!)")); - set_size_and_pos(ui_showname_enable, "showname_enable"); ui_showname_enable->setToolTip( tr("Display customized shownames for all users when checked.")); @@ -1390,7 +1357,7 @@ void Courtroom::set_background(QString p_background, bool display) ui_vp_message->hide(); ui_vp_chatbox->setVisible(chatbox_always_show); // Show it if chatbox always shows - if (ao_app->is_sticker_enabled() && chatbox_always_show) { + if (Options::getInstance().characterStickerEnabled() && chatbox_always_show) { ui_vp_sticker->load_image(m_chatmessage[CHAR_NAME]); } // Hide the face sticker @@ -1412,9 +1379,7 @@ void Courtroom::set_background(QString p_background, bool display) QString f_side = current_side; if (current_side == "") f_side = ao_app->get_char_side(current_char); - set_scene( - QString::number(ao_app->get_desk_mod(current_char, current_emote)), - f_side); + set_scene(true, f_side); } } @@ -1486,7 +1451,7 @@ void Courtroom::update_character(int p_cid, QString char_name, bool reset_emote) QString f_char; if (m_cid == -1) { - if (ao_app->is_discord_enabled()) + if (Options::getInstance().discordEnabled()) ao_app->discord->state_spectate(); f_char = ""; } @@ -1496,7 +1461,7 @@ void Courtroom::update_character(int p_cid, QString char_name, bool reset_emote) f_char = char_list.at(m_cid).name; } - if (ao_app->is_discord_enabled()) + if (Options::getInstance().discordEnabled()) ao_app->discord->state_character(f_char.toStdString()); } @@ -1602,11 +1567,6 @@ void Courtroom::enter_courtroom() else ui_additive->hide(); - if (ao_app->casing_alerts_supported) - ui_casing->show(); - else - ui_casing->hide(); - list_music(); list_areas(); @@ -1775,6 +1735,7 @@ void Courtroom::list_areas() void Courtroom::debug_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + Q_UNUSED(context); const QMap<QtMsgType, QString> colors = { {QtDebugMsg, "debug"}, {QtInfoMsg, "info"}, @@ -1814,7 +1775,7 @@ void Courtroom::append_server_chatmessage(QString p_name, QString p_message, ui_server_chatlog->append_chatmessage(p_name, p_message, color); - if (ao_app->get_text_logging_enabled() && !ao_app->log_filename.isEmpty()) { + if (Options::getInstance().logToTextFileEnabled() && !ao_app->log_filename.isEmpty()) { QString full = "[OOC][" + QDateTime::currentDateTimeUtc().toString() + "] " + p_name + ": " + p_message; ao_app->append_to_file(full, ao_app->log_filename, true); } @@ -1841,7 +1802,7 @@ void Courtroom::on_chat_return_pressed() return; ui_ic_chat_message->blockSignals(true); - QTimer::singleShot(ao_app->get_chat_ratelimit(), this, + QTimer::singleShot(Options::getInstance().chatRateLimit(), this, [this] { ui_ic_chat_message->blockSignals(false); }); // MS# // deskmod# @@ -1875,22 +1836,21 @@ void Courtroom::on_chat_return_pressed() else f_side = current_side; - QString f_desk_mod = "chat"; + int f_desk_mod = DESK_SHOW; if (ao_app->desk_mod_supported) { - f_desk_mod = - QString::number(ao_app->get_desk_mod(current_char, current_emote)); + f_desk_mod = ao_app->get_desk_mod(current_char, current_emote); if (!ao_app->expanded_desk_mods_supported) { - if (f_desk_mod == "2" || f_desk_mod == "4") - f_desk_mod = "0"; - else if (f_desk_mod == "3" || f_desk_mod == "5") - f_desk_mod = "1"; + if (f_desk_mod == DESK_PRE_ONLY_EX || f_desk_mod == DESK_PRE_ONLY) + f_desk_mod = DESK_HIDE; + else if (f_desk_mod == DESK_EMOTE_ONLY_EX || f_desk_mod == DESK_EMOTE_ONLY) + f_desk_mod = DESK_SHOW; } - if (f_desk_mod == "-1") - f_desk_mod = "chat"; + if (f_desk_mod == -1) + f_desk_mod = DESK_SHOW; } - packet_contents.append(f_desk_mod); + packet_contents.append(QString::number(f_desk_mod)); QString f_pre = ao_app->get_pre_emote(current_char, current_emote); int f_emote_mod = ao_app->get_emote_mod(current_char, current_emote); @@ -1945,7 +1905,7 @@ void Courtroom::on_chat_return_pressed() f_sfx = get_char_sfx(); // We have a custom sfx but we're on idle emotes. // Turn them into pre so the sound plays if client setting sfx_on_idle is enabled. - if (ao_app->get_sfx_on_idle() && (f_emote_mod == IDLE || f_emote_mod == ZOOM)) { + if (Options::getInstance().playSelectedSFXOnIdle() && (f_emote_mod == IDLE || f_emote_mod == ZOOM)) { // We turn idle into preanim, but make it not send a pre animation f_pre = ""; // Set sfx delay to 0 so the sfx plays immediately @@ -1985,7 +1945,7 @@ void Courtroom::on_chat_return_pressed() f_obj_state = QString::number(objection_state); // We're doing an Objection (custom objections not yet supported) - if (objection_state == 2 && ao_app->objection_stop_music()) + if (objection_state == 2 && Options::getInstance().objectionStopMusic()) music_stop(true); packet_contents.append(f_obj_state); @@ -2078,7 +2038,7 @@ void Courtroom::on_chat_return_pressed() QString packet; foreach (QString f_emote, emotes_to_check) { packet += f_emote; - if (ao_app->is_frame_network_enabled()) { + if (Options::getInstance().networkedFrameSfxEnabled()) { QString sfx_frames = ao_app ->read_ini_tags( @@ -2109,7 +2069,7 @@ void Courtroom::on_chat_return_pressed() } packet_contents.append(effect + "|" + p_effect_folder + "|" + fx_sound); - if (!ao_app->is_stickyeffects_enabled() && !ao_app->get_effect_property(effect, current_char, p_effect_folder, "sticky").startsWith("true")) { + if (!Options::getInstance().clearEffectsDropdownOnPlayEnabled() && !ao_app->get_effect_property(effect, current_char, p_effect_folder, "sticky").startsWith("true")) { ui_effects_dropdown->blockSignals(true); ui_effects_dropdown->setCurrentIndex(0); ui_effects_dropdown->blockSignals(false); @@ -2138,14 +2098,14 @@ void Courtroom::reset_ui() ui_evidence_present->set_image("present"); // If sticky sounds is disabled and we either have SFX on Idle enabled, or our Preanim checkbox is checked - if (!ao_app->is_stickysounds_enabled() && (ao_app->get_sfx_on_idle() || ui_pre->isChecked())) { + if (!Options::getInstance().clearSoundsDropdownOnPlayEnabled() && (Options::getInstance().playSelectedSFXOnIdle() || ui_pre->isChecked())) { // Reset the SFX Dropdown to "Default" ui_sfx_dropdown->setCurrentIndex(0); ui_sfx_remove->hide(); custom_sfx = ""; } // If sticky preanims is disabled - if (!ao_app->is_stickypres_enabled()) + if (!Options::getInstance().clearPreOnPlayEnabled()) // Turn off our Preanim checkbox ui_pre->setChecked(false); } @@ -2190,17 +2150,17 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents) reset_ui(); } // If we determine we sent this message, or we have desync enabled - if (sender || ao_app->is_desyncrhonized_logs_enabled()) { + if (sender || Options::getInstance().desynchronisedLogsEnabled()) { // Initialize operation "message queue ghost" log_chatmessage(p_contents[MESSAGE], p_contents[CHAR_ID].toInt(), p_contents[SHOWNAME], p_contents[CHAR_NAME], p_contents[OBJECTION_MOD], p_contents[EVIDENCE_ID].toInt(), - p_contents[TEXT_COLOR].toInt(), QUEUED, sender || ao_app->is_desyncrhonized_logs_enabled()); + p_contents[TEXT_COLOR].toInt(), QUEUED, sender || Options::getInstance().desynchronisedLogsEnabled()); } bool is_objection = false; // If the user wants to clear queue on objection - if (ao_app->is_instant_objection_enabled()) + if (Options::getInstance().objectionSkipQueueEnabled()) { int objection_mod = p_contents[OBJECTION_MOD].split("&")[0].toInt(); is_objection = objection_mod >= 1 && objection_mod <= 5; @@ -2217,7 +2177,7 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents) chatmessage_queue.enqueue(p_contents); // Our settings disabled queue, or no message is being parsed right now and we're not waiting on one - bool start_queue = ao_app->stay_time() <= 0 || (text_state >= 2 && !text_queue_timer->isActive()); + bool start_queue = Options::getInstance().textStayTime() <= 0 || (text_state >= 2 && !text_queue_timer->isActive()); // Objections also immediately play the message if (start_queue || is_objection) chatmessage_dequeue(); // Process the message instantly @@ -2242,7 +2202,7 @@ void Courtroom::skip_chatmessage_queue() while (!chatmessage_queue.isEmpty()) { QStringList p_contents = chatmessage_queue.dequeue(); // if the char ID matches our client's char ID (most likely, this is our message coming back to us) - bool sender = ao_app->is_desyncrhonized_logs_enabled() || p_contents[CHAR_ID].toInt() == m_cid; + bool sender = Options::getInstance().desynchronisedLogsEnabled() || p_contents[CHAR_ID].toInt() == m_cid; log_chatmessage(p_contents[MESSAGE], p_contents[CHAR_ID].toInt(), p_contents[SHOWNAME], p_contents[CHAR_NAME], p_contents[OBJECTION_MOD], p_contents[EVIDENCE_ID].toInt(), p_contents[TEXT_COLOR].toInt(), DISPLAY_ONLY, sender); } } @@ -2265,7 +2225,7 @@ void Courtroom::unpack_chatmessage(QStringList p_contents) } // if the char ID matches our client's char ID (most likely, this is our message coming back to us) - bool sender = ao_app->is_desyncrhonized_logs_enabled() || m_chatmessage[CHAR_ID].toInt() == m_cid; + bool sender = Options::getInstance().desynchronisedLogsEnabled() || m_chatmessage[CHAR_ID].toInt() == m_cid; // We have logs displaying as soon as we reach the message in our queue, which is a less confusing but also less accurate experience for the user. log_chatmessage(m_chatmessage[MESSAGE], m_chatmessage[CHAR_ID].toInt(), m_chatmessage[SHOWNAME], m_chatmessage[CHAR_NAME], m_chatmessage[OBJECTION_MOD], m_chatmessage[EVIDENCE_ID].toInt(), m_chatmessage[TEXT_COLOR].toInt(), DISPLAY_ONLY, sender); @@ -2501,19 +2461,17 @@ void Courtroom::display_character() ui_vp_message->hide(); ui_vp_chatbox->setVisible(chatbox_always_show); // Show it if chatbox always shows - if (ao_app->is_sticker_enabled() && chatbox_always_show) { + if (Options::getInstance().characterStickerEnabled() && chatbox_always_show) { ui_vp_sticker->load_image(m_chatmessage[CHAR_NAME]); } // Hide the face sticker else { ui_vp_sticker->stop(); } - // Initialize the correct pos (called SIDE here for some reason) with DESK_MOD to determine if we should hide the desk or not. - set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]); // Arrange the netstrings of the frame SFX for the character to know about if (!m_chatmessage[FRAME_SFX].isEmpty() && - ao_app->is_frame_network_enabled()) { + Options::getInstance().networkedFrameSfxEnabled()) { // ORDER IS IMPORTANT!! QStringList netstrings = {m_chatmessage[FRAME_SCREENSHAKE], m_chatmessage[FRAME_REALIZATION], @@ -2672,7 +2630,7 @@ void Courtroom::handle_ic_message() } // if we have instant objections disabled, and queue is not empty, check if next message after this is an objection. - if (!ao_app->is_instant_objection_enabled() && chatmessage_queue.size() > 0) + if (!Options::getInstance().objectionSkipQueueEnabled() && chatmessage_queue.size() > 0) { QStringList p_contents = chatmessage_queue.head(); int objection_mod = p_contents[OBJECTION_MOD].split("&")[0].toInt(); @@ -2685,7 +2643,7 @@ void Courtroom::handle_ic_message() void Courtroom::do_screenshake() { - if (!ao_app->is_shake_enabled()) + if (!Options::getInstance().shakeEnabled()) return; // This way, the animation is reset in such a way that last played screenshake @@ -2734,7 +2692,7 @@ void Courtroom::do_screenshake() void Courtroom::do_flash() { - if (!ao_app->is_effects_enabled()) + if (!Options::getInstance().effectsEnabled()) return; QString f_char = m_chatmessage[CHAR_NAME]; @@ -2758,7 +2716,7 @@ void Courtroom::do_effect(QString fx_path, QString fx_sound, QString p_char, } // Only check if effects are disabled after playing the sound if it exists - if (!ao_app->is_effects_enabled()) { + if (!Options::getInstance().effectsEnabled()) { return; } ui_vp_effect->transform_mode = ao_app->get_scaling( @@ -2855,7 +2813,7 @@ void Courtroom::initialize_chatbox() ui_vp_showname->setText(m_chatmessage[SHOWNAME]); } QString customchar; - if (ao_app->is_customchat_enabled()) + if (Options::getInstance().customChatboxEnabled()) customchar = m_chatmessage[CHAR_NAME]; QString p_misc = ao_app->get_chat(customchar); @@ -2966,8 +2924,8 @@ void Courtroom::handle_callwords() { // Quickly check through the message for the word_call (callwords) sfx QString f_message = m_chatmessage[MESSAGE]; - // Obtain the current call words (Really? It does File I/O on every single message???) - QStringList call_words = ao_app->get_call_words(); + //No more file IO on every message. + QStringList call_words = Options::getInstance().callwords(); // Loop through each word in the call words list for (const QString &word : qAsConst(call_words)) { // If our message contains that specific call word @@ -3297,7 +3255,7 @@ void Courtroom::log_ic_text(QString p_name, QString p_showname, { chatlogpiece log_entry(p_name, p_showname, p_message, p_action, p_color, p_selfname); ic_chatlog_history.append(log_entry); - if (ao_app->get_text_logging_enabled() && !ao_app->log_filename.isEmpty()) + if (Options::getInstance().logToTextFileEnabled() && !ao_app->log_filename.isEmpty()) ao_app->append_to_file(log_entry.get_full(), ao_app->log_filename, true); while (ic_chatlog_history.size() > log_maximum_blocks && @@ -3512,20 +3470,20 @@ void Courtroom::play_preanim(bool immediate) ui_vp_player_char->set_play_once(true); ui_vp_player_char->load_image(f_preanim, f_char, preanim_duration, true); - switch(m_chatmessage[DESK_MOD].toInt()) { - case 4: + switch (m_chatmessage[DESK_MOD].toInt()) { + case DESK_EMOTE_ONLY_EX: ui_vp_sideplayer_char->hide(); ui_vp_player_char->move_and_center(0, 0); [[fallthrough]]; - case 2: - set_scene("0", m_chatmessage[SIDE]); + case DESK_EMOTE_ONLY: + case DESK_HIDE: + set_scene(false, m_chatmessage[SIDE]); break; - case 5: - case 3: - set_scene("1", m_chatmessage[SIDE]); - break; - default: - set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]); + + case DESK_PRE_ONLY_EX: + case DESK_PRE_ONLY: + case DESK_SHOW: + set_scene(true, m_chatmessage[SIDE]); break; } @@ -3563,21 +3521,21 @@ void Courtroom::start_chat_ticking() // handle expanded desk mods switch(m_chatmessage[DESK_MOD].toInt()) { - case 4: + case DESK_EMOTE_ONLY_EX: set_self_offset(m_chatmessage[SELF_OFFSET]); [[fallthrough]]; - case 2: - set_scene("1", m_chatmessage[SIDE]); + case DESK_EMOTE_ONLY: + case DESK_SHOW: + set_scene(true, m_chatmessage[SIDE]); break; - case 5: + + case DESK_PRE_ONLY_EX: ui_vp_sideplayer_char->hide(); ui_vp_player_char->move_and_center(0, 0); [[fallthrough]]; - case 3: - set_scene("0", m_chatmessage[SIDE]); - break; - default: - set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]); + case DESK_PRE_ONLY: + case DESK_HIDE: + set_scene(false, m_chatmessage[SIDE]); break; } @@ -3616,7 +3574,7 @@ void Courtroom::start_chat_ticking() ui_vp_chatbox->setVisible(chatbox_always_show); ui_vp_message->hide(); // Show it if chatbox always shows - if (ao_app->is_sticker_enabled() && chatbox_always_show) + if (Options::getInstance().characterStickerEnabled() && chatbox_always_show) ui_vp_sticker->load_image(m_chatmessage[CHAR_NAME]); // Hide the face sticker else { @@ -3624,7 +3582,7 @@ void Courtroom::start_chat_ticking() } } // If we're not already waiting on the next message, start the timer. We could be overriden if there's an objection planned. - int delay = ao_app->stay_time(); + int delay = Options::getInstance().textStayTime(); if (delay > 0 && !text_queue_timer->isActive()) text_queue_timer->start(delay); return; @@ -3633,7 +3591,7 @@ void Courtroom::start_chat_ticking() ui_vp_chatbox->show(); ui_vp_message->show(); - if (ao_app->is_sticker_enabled()) + if (Options::getInstance().characterStickerEnabled()) ui_vp_sticker->load_image(m_chatmessage[CHAR_NAME]); if (m_chatmessage[ADDITIVE] != "1") { @@ -3644,9 +3602,9 @@ void Courtroom::start_chat_ticking() tick_pos = 0; blip_ticker = 0; - text_crawl = ao_app->get_text_crawl(); - blip_rate = ao_app->read_blip_rate(); - blank_blip = ao_app->get_blank_blip(); + text_crawl = Options::getInstance().textCrawlSpeed(); + blip_rate = Options::getInstance().blipRate(); + blank_blip = Options::getInstance().blankBlip(); // At the start of every new message, we set the text speed to the default. current_display_speed = 3; @@ -3707,7 +3665,7 @@ void Courtroom::chat_tick() anim_state = 3; QString f_char; QString f_custom_theme; - if (ao_app->is_customchat_enabled()) { + if (Options::getInstance().customChatboxEnabled()) { f_char = m_chatmessage[CHAR_NAME]; f_custom_theme = ao_app->get_chat(f_char); } @@ -3723,12 +3681,12 @@ void Courtroom::chat_tick() // If we're not already waiting on the next message, start the timer. We could be overriden if there's an objection planned. - int delay = ao_app->stay_time(); + int delay = Options::getInstance().textStayTime(); if (delay > 0 && !text_queue_timer->isActive()) text_queue_timer->start(delay); // if we have instant objections disabled, and queue is not empty, check if next message after this is an objection. - if (!ao_app->is_instant_objection_enabled() && chatmessage_queue.size() > 0) + if (!Options::getInstance().objectionSkipQueueEnabled() && chatmessage_queue.size() > 0) { QStringList p_contents = chatmessage_queue.head(); int objection_mod = p_contents[OBJECTION_MOD].split("&")[0].toInt(); @@ -3944,24 +3902,20 @@ void Courtroom::play_sfx() return; sfx_player->play(sfx_name); - if (ao_app->get_looping_sfx()) + if (Options::getInstance().loopingSfx()) sfx_player->set_looping( ao_app->get_sfx_looping(current_char, current_emote) == "1"); } -void Courtroom::set_scene(const QString f_desk_mod, const QString f_side) +void Courtroom::set_scene(bool show_desk, const QString f_side) { ui_vp_background->load_image(ao_app->get_pos_path(f_side)); ui_vp_desk->load_image(ao_app->get_pos_path(f_side, true)); - if (f_desk_mod == "0" || - (f_desk_mod != "1" && - (f_side == "jud" || f_side == "hld" || f_side == "hlp"))) { - ui_vp_desk->hide(); - } - else { + if (show_desk) ui_vp_desk->show(); - } + else + ui_vp_desk->hide(); } void Courtroom::set_self_offset(const QString& p_list) { @@ -4245,21 +4199,6 @@ void Courtroom::mod_called(QString p_ip) } } -void Courtroom::case_called(QString msg, bool def, bool pro, bool jud, bool jur, - bool steno) -{ - Q_UNUSED(def); - Q_UNUSED(pro); - Q_UNUSED(jud); - Q_UNUSED(jur); - Q_UNUSED(steno); - if (ui_casing->isChecked()) { - ui_server_chatlog->append(msg); - modcall_player->play(ao_app->get_court_sfx("case_call")); - ao_app->alert(this); - } -} - void Courtroom::on_ooc_return_pressed() { QString ooc_message = ui_ooc_chat_message->text(); @@ -4281,9 +4220,9 @@ void Courtroom::on_ooc_return_pressed() #else QStringList command = ooc_message.split(" ", Qt::SkipEmptyParts); #endif - QDir casefolder("base/cases"); + QDir casefolder(get_base_path()+"/cases"); if (!casefolder.exists()) { - QDir::current().mkdir("base/" + casefolder.dirName()); + QDir::current().mkdir(get_base_path() + casefolder.dirName()); append_server_chatmessage( "CLIENT", tr("You don't have a `base/cases/` folder! It was just made for you, " @@ -4320,7 +4259,7 @@ void Courtroom::on_ooc_return_pressed() return; } - QSettings casefile("base/cases/" + command[1] + ".ini", + QSettings casefile(get_base_path() + "/cases/" + command[1] + ".ini", QSettings::IniFormat); QString caseauth = casefile.value("author", "").value<QString>(); @@ -4381,9 +4320,9 @@ void Courtroom::on_ooc_return_pressed() #else QStringList command = ooc_message.split(" ", Qt::SkipEmptyParts); #endif - QDir casefolder("base/cases"); + QDir casefolder(get_base_path() + "cases"); if (!casefolder.exists()) { - QDir::current().mkdir("base/" + casefolder.dirName()); + QDir(get_base_path()).mkdir(casefolder.dirName()); append_server_chatmessage( "CLIENT", tr("You don't have a `base/cases/` folder! It was just made for you, " @@ -4417,7 +4356,7 @@ void Courtroom::on_ooc_return_pressed() ui_ooc_chat_message->clear(); return; } - QSettings casefile("base/cases/" + command[1] + ".ini", + QSettings casefile(get_base_path() + "/cases/" + command[1] + ".ini", QSettings::IniFormat); casefile.setValue("author", ui_ooc_chat_name->text()); casefile.setValue("cmdoc", ""); @@ -4637,7 +4576,7 @@ void Courtroom::on_iniswap_dropdown_changed(int p_index) } QString p_path = ao_app->get_real_path(VPath("iniswaps.ini")); if (!file_exists(p_path)) { - p_path = ao_app->get_base_path() + "iniswaps.ini"; + p_path = get_base_path() + "iniswaps.ini"; } ao_app->write_to_file(swaplist.join("\n"), p_path); ui_iniswap_dropdown->blockSignals(true); @@ -4787,7 +4726,7 @@ void Courtroom::on_sfx_context_menu_requested(const QPoint &pos) menu->addSeparator(); menu->addAction(QString("Open base sounds folder"), this, [=] { - QString p_path = ao_app->get_base_path() + "sounds/general/"; + QString p_path = get_base_path() + "sounds/general/"; if (!dir_exists(p_path)) { return; } @@ -4814,7 +4753,7 @@ void Courtroom::on_sfx_edit_requested() } if (!file_exists(p_path)) { - p_path = ao_app->get_base_path() + "soundlist.ini"; + p_path = get_base_path() + "soundlist.ini"; } QDesktopServices::openUrl(QUrl::fromLocalFile(p_path)); } @@ -5013,7 +4952,7 @@ void Courtroom::on_music_list_double_clicked(QTreeWidgetItem *p_item, { if (is_muted) return; - if (!ao_app->is_category_stop_enabled() && p_item->parent() == nullptr) + if (!Options::getInstance().stopMusicOnCategoryEnabled() && p_item->parent() == nullptr) return; column = 1; // Column 1 is always the metadata (which we want) QString p_song = p_item->text(column); @@ -5062,7 +5001,7 @@ void Courtroom::on_music_list_context_menu_requested(const QPoint &pos) menu->addSeparator(); menu->addAction(QString("Open base music folder"), this, [=] { - QString p_path = ao_app->get_base_path() + "sounds/music/"; + QString p_path = get_base_path() + "sounds/music/"; if (!dir_exists(p_path)) { return; } @@ -5388,7 +5327,7 @@ void Courtroom::on_text_color_context_menu_requested(const QPoint &pos) menu->addAction(QString("Open currently used chat_config.ini"), this, [=] { - QString p_path = ao_app->get_asset("chat_config.ini", ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, ao_app->get_chat(current_char)); + QString p_path = ao_app->get_asset("chat_config.ini", Options::getInstance().theme(), Options::getInstance().subTheme(), ao_app->default_theme, ao_app->get_chat(current_char)); if (!file_exists(p_path)) { return; } @@ -5578,8 +5517,6 @@ void Courtroom::on_change_character_clicked() void Courtroom::on_reload_theme_clicked() { - ao_app->reload_theme(); - set_courtroom_size(); set_widgets(); update_character(m_cid, ui_iniswap_dropdown->itemText(ui_iniswap_dropdown->currentIndex())); @@ -5648,11 +5585,6 @@ void Courtroom::on_call_mod_clicked() void Courtroom::on_settings_clicked() { ao_app->call_settings_menu(); } -void Courtroom::on_announce_casing_clicked() -{ - ao_app->call_announce_menu(this); -} - void Courtroom::on_pre_clicked() { ui_ic_chat_message->setFocus(); } void Courtroom::on_flip_clicked() { ui_ic_chat_message->setFocus(); } @@ -5707,7 +5639,7 @@ void Courtroom::on_evidence_context_menu_requested(const QPoint &pos) QMenu *menu = new QMenu(this); menu->addAction(QString("Open base evidence folder"), this, [=] { - QString p_path = ao_app->get_base_path() + "evidence/"; + QString p_path = get_base_path() + "evidence/"; if (!dir_exists(p_path)) { return; } @@ -5752,45 +5684,6 @@ qint64 Courtroom::pong() return ping_timer.elapsed(); } -void Courtroom::on_casing_clicked() -{ - if (ao_app->casing_alerts_supported) { - if (ui_casing->isChecked()) { - QStringList f_packet; - - f_packet.append(ao_app->get_casing_can_host_cases()); - f_packet.append(QString::number(ao_app->get_casing_cm_enabled())); - f_packet.append(QString::number(ao_app->get_casing_defence_enabled())); - f_packet.append( - QString::number(ao_app->get_casing_prosecution_enabled())); - f_packet.append(QString::number(ao_app->get_casing_judge_enabled())); - f_packet.append(QString::number(ao_app->get_casing_juror_enabled())); - f_packet.append(QString::number(ao_app->get_casing_steno_enabled())); - - ao_app->send_server_packet(new AOPacket("SETCASE", f_packet)); - } - else - ao_app->send_server_packet(new AOPacket("SETCASE", {"","0","0","0","0","0","0"})); - } -} - -void Courtroom::announce_case(QString title, bool def, bool pro, bool jud, - bool jur, bool steno) -{ - if (ao_app->casing_alerts_supported) { - QStringList f_packet; - - f_packet.append(title); - f_packet.append(QString::number(def)); - f_packet.append(QString::number(pro)); - f_packet.append(QString::number(jud)); - f_packet.append(QString::number(jur)); - f_packet.append(QString::number(steno)); - - ao_app->send_server_packet(new AOPacket("CASEA", f_packet)); - } -} - void Courtroom::start_clock(int id) { if (id >= 0 && id < max_clocks && ui_clock[id] != nullptr) @@ -5920,6 +5813,11 @@ void Courtroom::truncate_label_text(QWidget *p_widget, QString p_identifier) Courtroom::~Courtroom() { + //save sound settings + Options::getInstance().setMusicVolume(ui_music_slider->value()); + Options::getInstance().setSfxVolume(ui_sfx_slider->value()); + Options::getInstance().setBlipVolume(ui_blip_slider->value()); + delete music_player; delete sfx_player; delete objection_player; diff --git a/src/demoserver.cpp b/src/demoserver.cpp index bc7da1c1..16d2b46e 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -12,6 +12,11 @@ DemoServer::DemoServer(QObject *parent) : QObject(parent) connect(timer, &QTimer::timeout, this, &DemoServer::playback); } +void DemoServer::set_demo_file(QString filepath) +{ + filename = filepath; +} + void DemoServer::start_server() { if (server_started) return; @@ -35,13 +40,12 @@ void DemoServer::destroy_connection() void DemoServer::accept_connection() { - QString path = QFileDialog::getOpenFileName(nullptr, tr("Load Demo"), "logs/", tr("Demo Files (*.demo)")); - if (path.isEmpty()) + if (filename.isEmpty()) { destroy_connection(); return; } - load_demo(path); + load_demo(filename); if (demo_data.isEmpty()) { diff --git a/src/emotes.cpp b/src/emotes.cpp index 2a1d5066..899ae4e9 100644 --- a/src/emotes.cpp +++ b/src/emotes.cpp @@ -1,6 +1,7 @@ #include "courtroom.h" #include "aoemotebutton.h" +#include "options.h" void Courtroom::initialize_emotes() { @@ -200,7 +201,7 @@ void Courtroom::select_emote(int p_id) if (old_emote == current_emote) { ui_pre->setChecked(!ui_pre->isChecked()); } - else if (!ao_app->is_stickypres_enabled()) { + else if (!Options::getInstance().clearPreOnPlayEnabled()) { if (emote_mod == PREANIM || emote_mod == PREANIM_ZOOM) { ui_pre->setChecked(true); } diff --git a/src/evidence.cpp b/src/evidence.cpp index 337e8303..752ca47d 100644 --- a/src/evidence.cpp +++ b/src/evidence.cpp @@ -1,4 +1,5 @@ #include "courtroom.h" +#include "options.h" void Courtroom::initialize_evidence() { @@ -400,7 +401,7 @@ void Courtroom::on_evidence_image_name_edited() void Courtroom::on_evidence_image_button_clicked() { - QDir dir("base/evidence/"); + QDir dir(get_base_path() + "/evidence/"); QFileDialog dialog(this); dialog.setFileMode(QFileDialog::ExistingFile); dialog.setNameFilter(tr("Images (*.png)")); @@ -416,8 +417,8 @@ void Courtroom::on_evidence_image_button_clicked() return; QString filename = filenames.at(0); - QStringList bases = ao_app->get_mount_paths(); - bases.prepend(ao_app->get_base_path()); + QStringList bases = Options::getInstance().mountPaths(); + bases.prepend(get_base_path()); for (const QString &base : bases) { QDir baseDir(base); if (filename.startsWith(baseDir.absolutePath() + "/")) { @@ -453,7 +454,7 @@ void Courtroom::on_evidence_clicked(int p_id) else if (f_real_id > local_evidence_list.size()) return; - if (!ao_app->get_evidence_double_click()){ + if (!Options::getInstance().evidenceDoubleClickEdit()){ on_evidence_double_clicked(p_id); return; } diff --git a/src/file_functions.cpp b/src/file_functions.cpp index 95e9b5f4..92e598f8 100644 --- a/src/file_functions.cpp +++ b/src/file_functions.cpp @@ -26,3 +26,23 @@ bool exists(QString p_path) return file.exists(); } + +QString get_base_path() +{ + QString base_path = ""; +#ifdef ANDROID + QString sdcard_storage = getenv("SECONDARY_STORAGE"); + if (dir_exists(sdcard_storage + "/base/")) { + base_path = sdcard_storage + "/base/"; + } + else { + QString external_storage = getenv("EXTERNAL_STORAGE"); + base_path = external_storage + "/base/"; + } +#elif defined(__APPLE__) + base_path = QCoreApplication::applicationDirPath() + "/../../../base/"; +#else + base_path = QCoreApplication::applicationDirPath() + "/base/"; +#endif + return base_path; +} diff --git a/src/lobby.cpp b/src/lobby.cpp index c4eecb4b..a705b262 100644 --- a/src/lobby.cpp +++ b/src/lobby.cpp @@ -1,422 +1,282 @@ #include "lobby.h" #include "aoapplication.h" -#include "aosfxplayer.h" -#include "debug_functions.h" #include "demoserver.h" #include "networkmanager.h" +#include "widgets/add_server_dialog.h" +#include "widgets/direct_connect_dialog.h" +#include "widgets/edit_server_dialog.h" -#include <QAction> #include <QImageReader> -#include <QMenu> +#include <QLabel> +#include <QLineEdit> +#include <QPushButton> +#include <QTreeWidget> + +#include <QUiLoader> + +#define FROM_UI(type, name) \ + ; \ + ui_##name = findChild<type *>(#name); + +#define COMBO_RELOAD() \ + list_servers(); \ + list_favorites(); \ + list_demos(); \ + get_motd(); \ + check_for_updates(); \ + reset_selection(); -Lobby::Lobby(AOApplication *p_ao_app) : QMainWindow() +Lobby::Lobby(AOApplication *p_ao_app, NetworkManager *p_net_manager) + : QMainWindow() { ao_app = p_ao_app; - - this->setWindowTitle(tr("Attorney Online %1").arg(ao_app->applicationVersion())); - this->setWindowIcon(QIcon(":/logo.png")); - this->setWindowFlags( (this->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMaximizeButtonHint); - - ui_background = new AOImage(this, ao_app); - ui_background->setObjectName("ui_background"); - ui_public_servers = new AOButton(this, ao_app); - ui_public_servers->setObjectName("ui_public_servers"); - ui_favorites = new AOButton(this, ao_app); - ui_favorites->setObjectName("ui_favorites"); - ui_refresh = new AOButton(this, ao_app); - ui_refresh->setObjectName("ui_refresh"); - ui_add_to_fav = new AOButton(this, ao_app); - ui_add_to_fav->setObjectName("ui_add_to_fav"); - ui_remove_from_fav = new AOButton(this, ao_app); - ui_remove_from_fav->setObjectName("ui_remove_from_fav"); - ui_remove_from_fav->hide(); - ui_connect = new AOButton(this, ao_app); - ui_connect->setObjectName("ui_connect"); - ui_version = new QLabel(this); - ui_version->setObjectName("ui_version"); - ui_about = new AOButton(this, ao_app); - ui_about->setObjectName("ui_about"); - ui_settings = new AOButton(this, ao_app); - ui_settings->setObjectName("ui_settings"); - - ui_server_list = new QTreeWidget(this); - ui_server_list->setHeaderLabels({"#", "Name"}); - ui_server_list->setTextElideMode(Qt::ElideNone); - ui_server_list->header()->setMinimumSectionSize(24); - ui_server_list->header()->setSectionsMovable(false); - ui_server_list->setColumnWidth(0, 0); - ui_server_list->setIndentation(0); - ui_server_list->setObjectName("ui_server_list"); - ui_server_list->setContextMenuPolicy(Qt::CustomContextMenu); - - ui_server_search = new QLineEdit(this); - ui_server_search->setFrame(false); - ui_server_search->setPlaceholderText(tr("Search")); - ui_server_search->setObjectName("ui_server_search"); - - ui_player_count = new QLabel(this); - ui_player_count->setObjectName("ui_player_count"); - ui_description = new AOTextArea(this); - ui_description->setOpenExternalLinks(true); - ui_description->setObjectName("ui_description"); - ui_chatbox = new AOTextArea(this); - ui_chatbox->setOpenExternalLinks(true); - ui_chatbox->setObjectName("ui_chatbox"); - ui_loading_background = new AOImage(this, ao_app); - ui_loading_background->setObjectName("ui_loading_background"); - ui_loading_text = new QTextEdit(ui_loading_background); - ui_loading_text->setObjectName("ui_loading_text"); - ui_progress_bar = new QProgressBar(ui_loading_background); - ui_progress_bar->setMinimum(0); - ui_progress_bar->setMaximum(100); - ui_progress_bar->setObjectName("ui_progress_bar"); - ui_cancel = new AOButton(ui_loading_background, ao_app); - ui_cancel->setObjectName("ui_cancel"); - - connect(ui_public_servers, &AOButton::clicked, this, - &Lobby::on_public_servers_clicked); - connect(ui_favorites, &AOButton::clicked, this, &Lobby::on_favorites_clicked); - connect(ui_refresh, &AOButton::pressed, this, &Lobby::on_refresh_pressed); - connect(ui_refresh, &AOButton::released, this, &Lobby::on_refresh_released); - connect(ui_add_to_fav, &AOButton::pressed, this, - &Lobby::on_add_to_fav_pressed); - connect(ui_add_to_fav, &AOButton::released, this, - &Lobby::on_add_to_fav_released); - connect(ui_remove_from_fav, &AOButton::pressed, this, - &Lobby::on_remove_from_fav_pressed); - connect(ui_remove_from_fav, &AOButton::released, this, - &Lobby::on_remove_from_fav_released); - connect(ui_connect, &AOButton::pressed, this, &Lobby::on_connect_pressed); - connect(ui_connect, &AOButton::released, this, &Lobby::on_connect_released); - connect(ui_about, &AOButton::clicked, this, &Lobby::on_about_clicked); - connect(ui_settings, &AOButton::clicked, this, &Lobby::on_settings_clicked); - connect(ui_server_list, &QTreeWidget::itemClicked, this, - &Lobby::on_server_list_clicked); - connect(ui_server_list, &QTreeWidget::itemDoubleClicked, - this, &Lobby::on_server_list_doubleclicked); - connect(ui_server_list, &QTreeWidget::customContextMenuRequested, this, - &Lobby::on_server_list_context_menu_requested); - connect(ui_server_search, &QLineEdit::textChanged, this, - &Lobby::on_server_search_edited); - connect(ui_cancel, &AOButton::clicked, ao_app, &AOApplication::loading_cancelled); - - ui_connect->setEnabled(false); - - list_servers(); - get_motd(); - check_for_updates(); - - set_widgets(); + net_manager = p_net_manager; + + loadUI(); + COMBO_RELOAD() +} + +void Lobby::on_tab_changed(int index) +{ + switch (index) { + case SERVER: + current_page = SERVER; + ui_add_to_favorite_button->setVisible(true); + ui_remove_from_favorites_button->setVisible(false); + ui_add_server_button->setVisible(false); + ui_edit_favorite_button->setVisible(false); + ui_direct_connect_button->setVisible(true); + reset_selection(); + break; + case FAVORITES: + current_page = FAVORITES; + ui_add_to_favorite_button->setVisible(false); + ui_remove_from_favorites_button->setVisible(true); + ui_add_server_button->setVisible(true); + ui_edit_favorite_button->setVisible(true); + ui_direct_connect_button->setVisible(false); + reset_selection(); + break; + case DEMOS: + current_page = DEMOS; + ui_add_to_favorite_button->setVisible(false); + ui_add_server_button->setVisible(false); + ui_remove_from_favorites_button->setVisible(false); + ui_edit_favorite_button->setVisible(false); + ui_direct_connect_button->setVisible(false); + reset_selection(); + break; + default: + break; + } } -// sets images, position and size -void Lobby::set_widgets() +int Lobby::get_selected_server() { - ao_app->reload_theme(); - - QString filename = "lobby_design.ini"; - - pos_size_type f_lobby = ao_app->get_element_dimensions("lobby", filename); - - if (f_lobby.width < 0 || f_lobby.height < 0) { - qWarning() << "did not find lobby width or height in " << filename; - - #ifdef ANDROID - if(QtAndroid::checkPermission("android.permission.READ_EXTERNAL_STORAGE")==QtAndroid::PermissionResult::Denied) { - QtAndroid::requestPermissionsSync({"android.permission.READ_EXTERNAL_STORAGE","android.permission.WRITE_EXTERNAL_STORAGE"}); + switch (ui_connections_tabview->currentIndex()) { + case SERVER: + if (auto item = ui_serverlist_tree->currentItem()) { + return item->text(0).toInt(); } - #endif - - // Most common symptom of bad config files and missing assets. - call_notice( - tr("It doesn't look like your client is set up correctly.\n" - "Did you download all resources correctly from tiny.cc/getao, " - "including the large 'base' folder?")); - - this->setFixedSize(517, 666); - } - else { - this->setFixedSize(f_lobby.width, f_lobby.height); + break; + case FAVORITES: + if (auto item = ui_favorites_tree->currentItem()) { + return item->text(0).toInt(); + } + break; + default: + break; } - - set_size_and_pos(ui_background, "lobby"); - ui_background->set_image("lobbybackground"); - - set_size_and_pos(ui_public_servers, "public_servers"); - ui_public_servers->set_image("publicservers_selected"); - - set_size_and_pos(ui_favorites, "favorites"); - ui_favorites->set_image("favorites"); - - set_size_and_pos(ui_refresh, "refresh"); - ui_refresh->set_image("refresh"); - - set_size_and_pos(ui_add_to_fav, "add_to_fav"); - ui_add_to_fav->set_image("addtofav"); - - set_size_and_pos(ui_remove_from_fav, "remove_from_fav"); - ui_remove_from_fav->set_image("removefromfav"); - - set_size_and_pos(ui_connect, "connect"); - ui_connect->set_image("connect"); - - set_size_and_pos(ui_version, "version"); - ui_version->setText(tr("Version: %1").arg(ao_app->get_version_string())); - - set_size_and_pos(ui_about, "about"); - ui_about->set_image("about"); - - set_size_and_pos(ui_settings, "settings"); - ui_settings->setText(tr("Settings")); - ui_settings->set_image("lobby_settings"); - ui_settings->setToolTip( - tr("Allows you to change various aspects of the client.")); - - set_size_and_pos(ui_server_list, "server_list"); - - set_size_and_pos(ui_server_search, "server_search"); - - set_size_and_pos(ui_player_count, "player_count"); - ui_player_count->setText(tr("Offline")); - - set_size_and_pos(ui_description, "description"); - ui_description->setReadOnly(true); - - set_size_and_pos(ui_chatbox, "chatbox"); - ui_chatbox->setReadOnly(true); - - ui_loading_background->resize(this->width(), this->height()); - ui_loading_background->set_image("loadingbackground"); - - set_size_and_pos(ui_loading_text, "loading_label"); - ui_loading_text->setFont(QFont("Arial", 20, QFont::Bold)); - ui_loading_text->setReadOnly(true); - ui_loading_text->setAlignment(Qt::AlignCenter); - ui_loading_text->setFrameStyle(QFrame::NoFrame); - ui_loading_text->append(tr("Loading")); - - set_size_and_pos(ui_progress_bar, "progress_bar"); - set_size_and_pos(ui_cancel, "cancel"); - ui_cancel->setText(tr("Cancel")); - - ui_loading_background->hide(); - - set_fonts(); - set_stylesheets(); + return -1; } -void Lobby::set_size_and_pos(QWidget *p_widget, QString p_identifier) -{ - QString filename = "lobby_design.ini"; +int Lobby::pageSelected() { return current_page; } - pos_size_type design_ini_result = - ao_app->get_element_dimensions(p_identifier, filename); - - if (design_ini_result.width < 0 || design_ini_result.height < 0) { - qWarning() << "could not find" << p_identifier << "in" << filename; - p_widget->hide(); - } - else { - p_widget->move(design_ini_result.x, design_ini_result.y); - p_widget->resize(design_ini_result.width, design_ini_result.height); - } -} - -void Lobby::set_fonts() +void Lobby::reset_selection() { - set_font(ui_version, "version"); - set_font(ui_player_count, "player_count"); - set_font(ui_description, "description"); - set_font(ui_chatbox, "chatbox"); - set_font(ui_loading_text, "loading_text"); - set_font(ui_server_list, "server_list"); -} + last_index = -1; + ui_server_player_count_lbl->setText(tr("Offline")); + ui_server_description_text->clear(); -void Lobby::set_stylesheet(QWidget *widget) -{ - QString f_file = "lobby_stylesheets.css"; - QString style_sheet_string = ao_app->get_stylesheet(f_file); - if (style_sheet_string != "") - widget->setStyleSheet(style_sheet_string); + ui_edit_favorite_button->setEnabled(false); + ui_remove_from_favorites_button->setEnabled(false); + ui_connect_button->setEnabled(false); } -void Lobby::set_stylesheets() +void Lobby::loadUI() { - set_stylesheet(this); - this->setStyleSheet( - "QFrame { background-color:transparent; } " - "QAbstractItemView { background-color: transparent; color: black; } " - "QLineEdit { background-color:transparent; }" - + this->styleSheet() - ); -} + this->setWindowTitle( + tr("Attorney Online %1").arg(ao_app->applicationVersion())); + this->setWindowIcon(QIcon(":/logo.png")); + this->setWindowFlags((this->windowFlags() | Qt::CustomizeWindowHint)); -void Lobby::set_font(QWidget *widget, QString p_identifier) -{ - QString design_file = "lobby_fonts.ini"; - int f_weight = ao_app->get_font_size(p_identifier, design_file); - QString class_name = widget->metaObject()->className(); - QString font_name = - ao_app->get_design_element(p_identifier + "_font", design_file); - QFont font(font_name, f_weight); - bool use = ao_app->get_font_size("use_custom_fonts", design_file) == 1; - if (use) { - bool bold = ao_app->get_font_size(p_identifier + "_bold", design_file) == - 1; // is the font bold or not? - font.setBold(bold); - widget->setFont(font); - QColor f_color = ao_app->get_color(p_identifier + "_color", design_file); - bool center = - ao_app->get_font_size(p_identifier + "_center", design_file) == - 1; // should it be centered? - QString is_center = ""; - if (center) - is_center = "qproperty-alignment: AlignCenter;"; - QString style_sheet_string = - class_name + " { background-color: rgba(0, 0, 0, 0);\n" + - "color: rgba(" + QString::number(f_color.red()) + ", " + - QString::number(f_color.green()) + ", " + - QString::number(f_color.blue()) + ", 255);\n" + is_center + "}"; - widget->setStyleSheet(style_sheet_string); + QUiLoader l_loader(this); + QFile l_uiFile(Options::getInstance().getUIAsset(DEFAULT_UI)); + if (!l_uiFile.open(QFile::ReadOnly)) { + qCritical() << "Unable to open file " << l_uiFile.fileName(); + return; } - return; -} - -void Lobby::set_loading_text(QString p_text) -{ - ui_loading_text->clear(); - ui_loading_text->setAlignment(Qt::AlignCenter); - ui_loading_text->append(p_text); -} -QString Lobby::get_chatlog() -{ - QString return_value = ui_chatbox->toPlainText(); + l_loader.load(&l_uiFile, this); - return return_value; -} + FROM_UI(QLabel, game_version_lbl); + ui_game_version_lbl->setText( + tr("Version: %1").arg(ao_app->get_version_string())); -int Lobby::get_selected_server() -{ - if (auto item = ui_server_list->currentItem()) { - return item->text(0).toInt(); - } - return -1; -} + FROM_UI(QPushButton, settings_button); + connect(ui_settings_button, &QPushButton::clicked, this, + &Lobby::onSettingsRequested); -void Lobby::set_loading_value(int p_value) -{ - ui_progress_bar->setValue(p_value); -} + FROM_UI(QPushButton, about_button); + connect(ui_about_button, &QPushButton::clicked, this, + &Lobby::on_about_clicked); -void Lobby::on_public_servers_clicked() -{ - ui_public_servers->set_image("publicservers_selected"); - ui_favorites->set_image("favorites"); - ui_add_to_fav->show(); - ui_remove_from_fav->hide(); + // Serverlist elements + FROM_UI(QTabWidget, connections_tabview); + ui_connections_tabview->tabBar()->setExpanding(true); + connect(ui_connections_tabview, &QTabWidget::currentChanged, this, + &Lobby::on_tab_changed); - reset_selection(); + FROM_UI(QTreeWidget, serverlist_tree); + FROM_UI(QLineEdit, serverlist_search); + connect(ui_serverlist_tree, &QTreeWidget::itemClicked, this, + &Lobby::on_server_list_clicked); + connect(ui_serverlist_tree, &QTreeWidget::itemDoubleClicked, this, + &Lobby::on_list_doubleclicked); + connect(ui_serverlist_search, &QLineEdit::textChanged, this, + &Lobby::on_server_search_edited); - public_servers_selected = true; + FROM_UI(QTreeWidget, favorites_tree); + connect(ui_favorites_tree, &QTreeWidget::itemClicked, this, + &Lobby::on_favorite_tree_clicked); + connect(ui_favorites_tree, &QTreeWidget::itemDoubleClicked, this, + &Lobby::on_list_doubleclicked); - list_servers(); -} + FROM_UI(QTreeWidget, demo_tree); + connect(ui_demo_tree, &QTreeWidget::itemClicked, this, + &Lobby::on_demo_clicked); + connect(ui_demo_tree, &QTreeWidget::itemDoubleClicked, this, + &Lobby::on_list_doubleclicked); -void Lobby::on_favorites_clicked() -{ - ui_public_servers->set_image("publicservers"); - ui_favorites->set_image("favorites_selected"); - ui_add_to_fav->hide(); - ui_remove_from_fav->show(); + FROM_UI(QPushButton, refresh_button); + connect(ui_refresh_button, &QPushButton::released, this, + &Lobby::on_refresh_released); - reset_selection(); + FROM_UI(QPushButton, direct_connect_button); + connect(ui_direct_connect_button, &QPushButton::released, this, + &Lobby::on_direct_connect_released); - ao_app->load_favorite_list(); + FROM_UI(QPushButton, add_to_favorite_button) + connect(ui_add_to_favorite_button, &QPushButton::released, this, + &Lobby::on_add_to_fav_released); - public_servers_selected = false; + FROM_UI(QPushButton, add_server_button) + ui_add_server_button->setVisible(false); + connect(ui_add_server_button, &QPushButton::released, this, + &Lobby::on_add_server_to_fave_released); - list_favorites(); -} + FROM_UI(QPushButton, edit_favorite_button) + ui_edit_favorite_button->setVisible(false); + connect(ui_edit_favorite_button, &QPushButton::released, this, + &Lobby::on_edit_favorite_released) -void Lobby::reset_selection() -{ - last_index = -1; - ui_server_list->clearSelection(); - ui_player_count->setText(tr("Offline")); - ui_description->clear(); + FROM_UI(QPushButton, remove_from_favorites_button) + ui_remove_from_favorites_button->setVisible(false); + connect(ui_remove_from_favorites_button, &QPushButton::released, this, + &Lobby::on_remove_from_fav_released); - ui_connect->setEnabled(false); + FROM_UI(QLabel, server_player_count_lbl) + FROM_UI(QTextBrowser, server_description_text) + FROM_UI(QPushButton, connect_button); + connect(ui_connect_button, &QPushButton::released, net_manager, + &NetworkManager::join_to_server); + connect(ui_connect_button, &QPushButton::released, this, [=] { + ui_server_player_count_lbl->setText(tr("Joining Server...")); + }); + connect(net_manager, &NetworkManager::server_connected, ui_connect_button, + &QPushButton::setEnabled); + + FROM_UI(QTextBrowser, motd_text); + FROM_UI(QTextBrowser, game_changelog_text) + if (ui_game_changelog_text != nullptr) { + QString l_changelog_text = "No changelog found."; + QFile l_changelog(get_base_path() + "changelog.md"); + if (!l_changelog.open(QFile::ReadOnly)) { + qDebug() << "Unable to locate changelog file. Does it even exist?"; +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + ui_game_changelog_text->setMarkdown(l_changelog_text); +#else + ui_game_changelog_text->setPlainText( + l_changelog_text); // imperfect solution, but implementing Markdown + // ourselves for this edge case is out of scope +#endif + return; + } +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + ui_game_changelog_text->setMarkdown(l_changelog.readAll()); +#else + ui_game_changelog_text->setPlainText((l_changelog.readAll())); +#endif + l_changelog.close(); + + QTabWidget *l_tabbar = findChild<QTabWidget *>("motd_changelog_tab"); + if (l_tabbar != nullptr) { + l_tabbar->tabBar()->setExpanding(true); + } + } } -void Lobby::on_refresh_pressed() { ui_refresh->set_image("refresh_pressed"); } - void Lobby::on_refresh_released() { - ui_refresh->set_image("refresh"); - - if (public_servers_selected) { - ao_app->net_manager->get_server_list(std::bind(&Lobby::list_servers, this)); - get_motd(); - } else { - ao_app->load_favorite_list(); - list_favorites(); - } + net_manager->get_server_list(std::bind(&Lobby::list_servers, this)); + get_motd(); + list_favorites(); } -void Lobby::on_add_to_fav_pressed() +void Lobby::on_direct_connect_released() { - ui_add_to_fav->set_image("addtofav_pressed"); + DirectConnectDialog connect_dialog(net_manager); + connect_dialog.exec(); } void Lobby::on_add_to_fav_released() { - ui_add_to_fav->set_image("addtofav"); - if (public_servers_selected) { - int selection = get_selected_server(); - if (selection > -1) { - ao_app->add_favorite_server(selection); - } + int selection = get_selected_server(); + if (selection > -1) { + Options::getInstance().addFavorite(ao_app->get_server_list().at(selection)); + list_favorites(); } } -void Lobby::on_remove_from_fav_pressed() +void Lobby::on_add_server_to_fave_released() { - ui_remove_from_fav->set_image("removefromfav_pressed"); + AddServerDialog l_dialog; + l_dialog.exec(); + list_favorites(); + reset_selection(); } -void Lobby::on_remove_from_fav_released() +void Lobby::on_edit_favorite_released() { - ui_remove_from_fav->set_image("removefromfav"); - if (public_servers_selected) { - return; - } + EditServerDialog l_dialog(get_selected_server()); + l_dialog.exec(); + list_favorites(); + reset_selection(); +} +void Lobby::on_remove_from_fav_released() +{ int selection = get_selected_server(); - if (selection > 0) { - ao_app->remove_favorite_server(selection); + if (selection >= 0) { + Options::getInstance().removeFavorite(selection); list_favorites(); } } -void Lobby::on_connect_pressed() { ui_connect->set_image("connect_pressed"); } - -void Lobby::on_connect_released() -{ - ui_connect->set_image("connect"); - - AOPacket *f_packet; - - f_packet = new AOPacket("askchaa"); - - ao_app->send_server_packet(f_packet); -} - void Lobby::on_about_clicked() { const bool hasApng = QImageReader::supportedImageFormats().contains("apng"); - QString msg = tr("<h2>Attorney Online %1</h2>" "The courtroom drama simulator." @@ -427,18 +287,20 @@ void Lobby::on_about_clicked() "OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, " "Crystalwarrior, Iamgoofball, in1tiate" "<p><b>Client development:</b><br>" - "Cents02, windrammer, skyedeving, TrickyLeifa, Salanto" + "Cents02, windrammer, skyedeving, TrickyLeifa, Salanto, lambdcalculus" "<p><b>QA testing:</b><br>" "CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, " "Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, " "Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, " "Veritas, Wiso" "<p><b>Translations:</b><br>" - "k-emiko (Русский), Pyraq (Polski), scatterflower (日本語), vintprox (Русский), " + "k-emiko (Русский), Pyraq (Polski), scatterflower (日本語), vintprox " + "(Русский), " "windrammer (Español, Português)" "<p><b>Special thanks:</b><br>" "Wiso, dyviacat (2.10 release); " - "CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); " + "CrazyJC (2.8 release director) and MaximumVolty (2.8 release " + "promotion); " "Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); " "Rue (website); Draxirch (UI design); " "Lewdton and Argoneus (tsuserver); " @@ -452,100 +314,90 @@ void Lobby::on_about_clicked() "<p>Running on Qt version %2 with the BASS audio engine.<br>" "APNG plugin loaded: %3" "<p>Built on %4") - .arg(ao_app->get_version_string()) - .arg(QLatin1String(QT_VERSION_STR)) - .arg(hasApng ? tr("Yes") : tr("No")) - .arg(QLatin1String(__DATE__)); + .arg(ao_app->get_version_string()) + .arg(QLatin1String(QT_VERSION_STR)) + .arg(hasApng ? tr("Yes") : tr("No")) + .arg(QLatin1String(__DATE__)); QMessageBox::about(this, tr("About"), msg); } -void Lobby::on_settings_clicked() { ao_app->call_settings_menu(); } - // clicked on an item in the serverlist void Lobby::on_server_list_clicked(QTreeWidgetItem *p_item, int column) { column = 0; - if (p_item->text(column).toInt() != last_index || !public_servers_selected) { - server_type f_server; - int n_server = p_item->text(column).toInt(); - last_index = n_server; + server_type f_server; + int n_server = p_item->text(column).toInt(); - if (n_server < 0) - return; + if (n_server == last_index) { + return; + } + last_index = n_server; - if (public_servers_selected) { - QVector<server_type> f_server_list = ao_app->get_server_list(); + if (n_server < 0) return; - if (n_server >= f_server_list.size()) - return; + QVector<server_type> f_server_list = ao_app->get_server_list(); - f_server = f_server_list.at(n_server); - } - else { - if (n_server >= ao_app->get_favorite_list().size()) - return; - - f_server = ao_app->get_favorite_list().at(n_server); - } + if (n_server >= f_server_list.size()) return; - set_server_description(f_server.desc); + f_server = f_server_list.at(n_server); - ui_description->moveCursor(QTextCursor::Start); - ui_description->ensureCursorVisible(); + set_server_description(f_server.desc); - ui_player_count->setText(tr("Offline")); + ui_server_description_text->moveCursor(QTextCursor::Start); + ui_server_description_text->ensureCursorVisible(); + ui_server_player_count_lbl->setText(tr("Connecting...")); - ui_connect->setEnabled(false); + ui_connect_button->setEnabled(false); - if (f_server.port == 99999 && f_server.ip == "127.0.0.1") { - // Demo playback server selected - ao_app->demo_server->start_server(); - server_type demo_server; - demo_server.ip = "127.0.0.1"; - demo_server.port = ao_app->demo_server->port; - ao_app->net_manager->connect_to_server(demo_server); - } - else ao_app->net_manager->connect_to_server(f_server); - } + net_manager->connect_to_server(f_server); } // doubleclicked on an item in the serverlist so we'll connect right away -void Lobby::on_server_list_doubleclicked(QTreeWidgetItem *p_item, int column) +void Lobby::on_list_doubleclicked(QTreeWidgetItem *p_item, int column) { - doubleclicked = true; - on_server_list_clicked(p_item, column); - //on_connect_released(); + Q_UNUSED(p_item) + Q_UNUSED(column) + ui_server_player_count_lbl->setText(tr("Joining Server...")); + net_manager->join_to_server(); } -void Lobby::on_server_list_context_menu_requested(const QPoint &point) +void Lobby::on_favorite_tree_clicked(QTreeWidgetItem *p_item, int column) { - if (public_servers_selected) { - return; - } + column = 0; + server_type f_server; + int n_server = p_item->text(column).toInt(); - auto *item = ui_server_list->itemAt(point); - if (item == nullptr) { - qInfo() << "no favorite server item; skipping context menu"; - return; - } - const int server_index = item->data(0, Qt::DisplayRole).toInt(); - if (server_index == 0) { - qInfo() << "demo server has no context menu to display"; + if (n_server == last_index) { return; } + last_index = n_server; - auto *menu = new QMenu(this); - menu->addAction(tr("Remove"), ao_app, [this,server_index](){ - ao_app->remove_favorite_server(server_index); - list_favorites(); - }); - menu->popup(ui_server_list->mapToGlobal(point)); + if (n_server < 0) return; + + ui_add_server_button->setEnabled(true); + ui_edit_favorite_button->setEnabled(true); + ui_remove_from_favorites_button->setEnabled(true); + + QVector<server_type> f_server_list = Options::getInstance().favorites(); + + if (n_server >= f_server_list.size()) return; + + f_server = f_server_list.at(n_server); + + set_server_description(f_server.desc); + ui_server_description_text->moveCursor(QTextCursor::Start); + ui_server_description_text->ensureCursorVisible(); + ui_server_player_count_lbl->setText(tr("Connecting...")); + + ui_connect_button->setEnabled(false); + + net_manager->connect_to_server(f_server); } void Lobby::on_server_search_edited(QString p_text) { // Iterate through all QTreeWidgetItem items - QTreeWidgetItemIterator it(ui_server_list); + QTreeWidgetItemIterator it(ui_serverlist_tree); while (*it) { (*it)->setHidden(p_text != ""); ++it; @@ -553,8 +405,9 @@ void Lobby::on_server_search_edited(QString p_text) if (p_text != "") { // Search in metadata - QList<QTreeWidgetItem *> clist = ui_server_list->findItems( - ui_server_search->text(), Qt::MatchContains | Qt::MatchRecursive, 1); + QList<QTreeWidgetItem *> clist = ui_serverlist_tree->findItems( + ui_serverlist_search->text(), Qt::MatchContains | Qt::MatchRecursive, + 1); foreach (QTreeWidgetItem *item, clist) { if (item->parent() != nullptr) // So the category shows up too item->parent()->setHidden(false); @@ -563,98 +416,137 @@ void Lobby::on_server_search_edited(QString p_text) } } -void Lobby::list_servers() +void Lobby::on_demo_clicked(QTreeWidgetItem *item, int column) { - if (!public_servers_selected) { + Q_UNUSED(column) + + if (item == nullptr) { return; } - ui_favorites->set_image("favorites"); - ui_public_servers->set_image("publicservers_selected"); - ui_server_list->setSortingEnabled(false); - ui_server_list->clear(); + QString l_filepath = (QApplication::applicationDirPath() + "/logs/%1/%2") + .arg(item->data(0, Qt::DisplayRole).toString(), + item->data(1, Qt::DisplayRole).toString()); + ao_app->demo_server->start_server(); + server_type demo_server; + demo_server.ip = "127.0.0.1"; + demo_server.port = ao_app->demo_server->port; + ao_app->demo_server->set_demo_file(l_filepath); + net_manager->connect_to_server(demo_server); +} + +void Lobby::onReloadThemeRequested() +{ + // This is destructive to the active widget data. + // Whatever, this is lobby. Nothing here is worth saving. + delete centralWidget(); + loadUI(); + COMBO_RELOAD() +} + +void Lobby::onSettingsRequested() +{ + AOOptionsDialog options(nullptr, ao_app); + connect(&options, &AOOptionsDialog::reloadThemeRequest, this, + &Lobby::onReloadThemeRequested); + options.exec(); +} + +void Lobby::list_servers() +{ + ui_serverlist_tree->setSortingEnabled(false); + ui_serverlist_tree->clear(); - ui_server_search->setText(""); + ui_serverlist_search->setText(""); int i = 0; for (const server_type &i_server : qAsConst(ao_app->get_server_list())) { - QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_server_list); + QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_serverlist_tree); treeItem->setData(0, Qt::DisplayRole, i); treeItem->setText(1, i_server.name); i++; } - ui_server_list->setSortingEnabled(true); - ui_server_list->sortItems(0, Qt::SortOrder::AscendingOrder); + ui_serverlist_tree->setSortingEnabled(true); + ui_serverlist_tree->sortItems(0, Qt::SortOrder::AscendingOrder); + ui_serverlist_tree->resizeColumnToContents(0); } void Lobby::list_favorites() { - if (public_servers_selected) { - return; - } - ui_server_list->setSortingEnabled(false); - ui_server_list->clear(); + ui_favorites_tree->setSortingEnabled(false); + ui_favorites_tree->clear(); int i = 0; - for (const server_type &i_server : qAsConst(ao_app->get_favorite_list())) { - QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_server_list); + for (const server_type &i_server : Options::getInstance().favorites()) { + QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_favorites_tree); treeItem->setData(0, Qt::DisplayRole, i); treeItem->setText(1, i_server.name); - // treeItem->setText(2, "-"); i++; } - ui_server_list->setSortingEnabled(true); + ui_favorites_tree->setSortingEnabled(true); + ui_favorites_tree->sortItems(0, Qt::SortOrder::AscendingOrder); + ui_favorites_tree->resizeColumnToContents(0); } -void Lobby::get_motd() +void Lobby::list_demos() { - ao_app->net_manager->request_document(MSDocumentType::Motd, - [this](QString document) { - if (document.isEmpty()) { - document = tr("Couldn't get the message of the day."); + ui_demo_tree->setSortingEnabled(false); + ui_demo_tree->clear(); + + QMultiMap<QString, QString> m_demo_entries = ao_app->load_demo_logs_list(); + for (auto &l_key : m_demo_entries.uniqueKeys()) { + for (const QString &l_entry : m_demo_entries.values(l_key)) { + QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_demo_tree); + treeItem->setData(0, Qt::DisplayRole, l_key); + treeItem->setData(1, Qt::DisplayRole, l_entry); } - ui_chatbox->setHtml(document); - }); + } + ui_demo_tree->setSortingEnabled(true); + ui_demo_tree->sortItems(0, Qt::SortOrder::AscendingOrder); + ui_demo_tree->resizeColumnToContents(0); } -void Lobby::check_for_updates() +void Lobby::get_motd() { - ao_app->net_manager->request_document(MSDocumentType::ClientVersion, - [this](QString version) { - const QString current_version = ao_app->get_version_string(); - if (!version.isEmpty() && version != current_version) { - ui_version->setText(tr("Version: %1 (!)").arg(current_version)); - ui_version->setToolTip(tr("New version available: %1").arg(version)); + net_manager->request_document(MSDocumentType::Motd, [this](QString document) { + if (document.isEmpty()) { + document = tr("Couldn't get the message of the day."); } + ui_motd_text->setHtml(document); }); } -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()); -} - -void Lobby::append_error(QString f_message) +void Lobby::check_for_updates() { - ui_chatbox->append_error(f_message); + net_manager->request_document( + MSDocumentType::ClientVersion, [this](QString version) { + const QString current_version = ao_app->get_version_string(); + if (!version.isEmpty() && version != current_version) { + ui_game_version_lbl->setText( + tr("Version: %1 (!)").arg(current_version)); + ui_game_version_lbl->setToolTip( + tr("New version available: %1").arg(version)); + } + }); } void Lobby::set_player_count(int players_online, int max_players) { - QString f_string = tr("Online: %1/%2").arg( - QString::number(players_online), - QString::number(max_players)); - ui_player_count->setText(f_string); + QString f_string = + tr("Online: %1/%2") + .arg(QString::number(players_online), QString::number(max_players)); + ui_server_player_count_lbl->setText(f_string); } -void Lobby::set_server_description(const QString& server_description) +void Lobby::set_server_description(const QString &server_description) { - ui_description->clear(); - ui_description->append_linked(server_description); + ui_server_description_text->clear(); + QString result = + server_description.toHtmlEscaped() + .replace("\n", "<br>") + .replace(QRegularExpression("\\b(https?://\\S+\\.\\S+)\\b"), + "<a href='\\1'>\\1</a>"); + ui_server_description_text->insertHtml(result); } -void Lobby::enable_connect_button() { ui_connect->setEnabled(true); } - Lobby::~Lobby() {} diff --git a/src/main.cpp b/src/main.cpp index e8ffe67e..5b696fef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include <QLibraryInfo> #include <QPluginLoader> #include <QTranslator> +#include <QResource> int main(int argc, char *argv[]) { @@ -16,16 +17,21 @@ int main(int argc, char *argv[]) AOApplication main_app(argc, argv); + #ifdef ANDROID + if(QtAndroid::checkPermission("android.permission.READ_EXTERNAL_STORAGE")==QtAndroid::PermissionResult::Denied) { + QtAndroid::requestPermissionsSync({"android.permission.READ_EXTERNAL_STORAGE","android.permission.WRITE_EXTERNAL_STORAGE"}); + } + #endif + AOApplication::addLibraryPath(AOApplication::applicationDirPath() + "/lib"); + QResource::registerResource(main_app.get_asset("themes/" + Options::getInstance().theme() + ".rcc")); QFontDatabase fontDatabase; - QDirIterator it(main_app.get_base_path() + "fonts", + QDirIterator it(get_base_path() + "fonts", QDirIterator::Subdirectories); while (it.hasNext()) fontDatabase.addApplicationFont(it.next()); - QSettings *configini = main_app.configini; - QPluginLoader apngPlugin("qapng"); if (!apngPlugin.load()) qCritical() << "QApng plugin could not be loaded"; @@ -35,7 +41,7 @@ int main(int argc, char *argv[]) qCritical() << "QWebp plugin could not be loaded"; QString p_language = - configini->value("language", QLocale::system().name()).toString(); + Options::getInstance().language(); if (p_language == " " || p_language == "") p_language = QLocale::system().name(); diff --git a/src/networkmanager.cpp b/src/networkmanager.cpp index 6d01a30e..96e262a5 100644 --- a/src/networkmanager.cpp +++ b/src/networkmanager.cpp @@ -3,10 +3,12 @@ #include "datatypes.h" #include "debug_functions.h" #include "lobby.h" +#include "options.h" #include <QAbstractSocket> #include <QJsonArray> #include <QJsonDocument> +#include <QJsonObject> #include <QNetworkReply> NetworkManager::NetworkManager(AOApplication *parent) : QObject(parent) @@ -17,7 +19,7 @@ NetworkManager::NetworkManager(AOApplication *parent) : QObject(parent) heartbeat_timer = new QTimer(this); QString master_config = - ao_app->configini->value("master", "").value<QString>(); + Options::getInstance().alternativeMasterserver(); if (!master_config.isEmpty() && QUrl(master_config).scheme().startsWith("http")) { qInfo() << "using alternate master server" << master_config; ms_baseurl = master_config; @@ -81,7 +83,7 @@ void NetworkManager::send_heartbeat() // within a 5 minute window, so that the the number of people playing within // that time period can be counted and an accurate player count be displayed. // What do I care about your personal information, I really don't want it. - if (ao_app->get_player_count_optout()) + if (Options::getInstance().playerCountOptout()) return; QNetworkRequest req(QUrl(ms_baseurl + "/playing")); @@ -105,7 +107,7 @@ void NetworkManager::request_document(MSDocumentType document_type, req.setRawHeader("User-Agent", get_user_agent().toUtf8()); QString language = - ao_app->configini->value("language").toString(); + Options::getInstance().language(); if (language.trimmed().isEmpty()) language = QLocale::system().name(); @@ -192,6 +194,11 @@ void NetworkManager::connect_to_server(server_type p_server) active_connection_type = p_server.socket_type; } +void NetworkManager::join_to_server() +{ + ship_server_packet(AOPacket("askchaa").to_string()); +} + void NetworkManager::disconnect_from_server() { if (!connected) diff --git a/src/options.cpp b/src/options.cpp new file mode 100644 index 00000000..4c32e963 --- /dev/null +++ b/src/options.cpp @@ -0,0 +1,703 @@ +#include "options.h" +#include "file_functions.h" + +#include <QCoreApplication> +#include <QDebug> +#include <QFile> +#include <QLocale> +#include <QObject> +#include <QRegularExpression> +#include <QSize> + +void Options::migrateCallwords() +{ + // Bla bla, evil boilerplate. + QStringList l_callwords; + + QFile l_file; + l_file.setFileName(get_base_path() + "callwords.ini"); + + if (!l_file.open(QIODevice::ReadOnly)) { + qWarning() << "Unable to migrate callwords : File not open."; + return; + } + + QTextStream in(&l_file); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + in.setCodec("UTF-8"); +#endif + + while (!in.atEnd()) { + QString line = in.readLine(); + l_callwords.append(line); + } + l_file.close(); + l_file.remove(); + + setCallwords(l_callwords); +} + +Options::Options() + : config(get_base_path() + "config.ini", QSettings::IniFormat, nullptr), + favorite(get_base_path() + "favorite_servers.ini", QSettings::IniFormat, + nullptr) +{ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + config.setIniCodec("UTF-8"); +#endif + migrate(); + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + favorite.setIniCodec("UTF-8"); +#endif +} + +/*! Migrate old configuration keys/values to a relevant format. */ +void Options::migrate() +{ + if (config.contains("show_custom_shownames")) { + config.remove("show_custom_shownames"); + } + if (QFile::exists(get_base_path() + "callwords.ini")) { + migrateCallwords(); + } + if (config.contains("ooc_name")) { + if (username().isEmpty()) { + config.setValue("default_username", config.value("ooc_name")); + } + config.remove("ooc_name"); + } + + if (config.contains("casing_enabled")) { + config.remove("casing_enabled"); + config.remove("casing_defence_enabled"); + config.remove("casing_prosecution_enabled"); + config.remove("casing_judge_enabled"); + config.remove("casing_juror_enabled"); + config.remove("casing_steno_enabled"); + config.remove("casing_cm_enabled"); + config.remove("casing_can_host_cases"); + } +} + +QString Options::theme() const +{ + return config.value("theme", "default").toString(); +} + +void Options::setTheme(QString value) { config.setValue("theme", value); } + +int Options::blipRate() const { return config.value("blip_rate", 2).toInt(); } + +void Options::setBlipRate(int value) { config.setValue("blip_rate", value); } + +int Options::musicVolume() const +{ + return config.value("default_music", 50).toInt(); +} + +void Options::setMusicVolume(int value) +{ + config.setValue("default_music", value); +} + +int Options::sfxVolume() const +{ + return config.value("default_sfx", 50).toInt(); +} + +void Options::setSfxVolume(int value) { config.setValue("default_sfx", value); } + +int Options::blipVolume() const +{ + return config.value("default_blip", 50).toInt(); +} + +void Options::setBlipVolume(int value) +{ + config.setValue("default_blip", value); +} + +int Options::defaultSuppressAudio() const +{ + return config.value("suppress_audio", 50).toInt(); +} + +void Options::setDefaultSupressedAudio(int value) +{ + config.setValue("suppress_audio", value); +} + +int Options::maxLogSize() const +{ + return config.value("log_maximum", 200).toInt(); +} + +void Options::setMaxLogSize(int value) +{ + config.setValue("log_maximum", value); +} + +int Options::textStayTime() const +{ + return config.value("stay_time", 200).toInt(); +} + +void Options::setTextStayTime(int value) +{ + config.setValue("stay_time", value); +} + +int Options::textCrawlSpeed() const +{ + return config.value("text_crawl", 40).toInt(); +} + +void Options::setTextCrawlSpeed(int value) +{ + config.setValue("text_crawl", value); +} + +int Options::chatRateLimit() const +{ + return config.value("chat_ratelimit", 300).toInt(); +} + +void Options::setChatRateLimit(int value) +{ + config.setValue("chat_ratelimit", value); +} + +bool Options::logDirectionDownwards() const +{ + return config.value("log_goes_downwards", true).toBool(); +} + +void Options::setLogDirectionDownwards(bool value) +{ + config.setValue("log_goes_downwards", value); +} + +bool Options::logNewline() const +{ + return config.value("log_newline", false).toBool(); +} + +void Options::setLogNewline(bool value) +{ + config.setValue("log_newline", value); +} + +int Options::logMargin() const { return config.value("log_margin", 0).toInt(); } + +void Options::setLogMargin(int value) { config.setValue("log_margin", value); } + +bool Options::logTimestampEnabled() const +{ + return config.value("log_timestamp", false).toBool(); +} + +void Options::setLogTimestampEnabled(bool value) +{ + config.setValue("log_timestamp", value); +} + +QString Options::logTimestampFormat() const +{ + return config.value("log_timestamp_format", "h:mm:ss AP").toString(); +} + +void Options::setLogTimestampFormat(QString value) +{ + config.setValue("log_timestamp_format", value); +} + +bool Options::logIcActions() const +{ + return config.value("log_ic_actions", true).toBool(); +} + +void Options::setLogIcActions(bool value) +{ + config.setValue("log_ic_actions", value); +} + +bool Options::customShownameEnabled() const +{ + return config.value("show_custom_shownames", true).toBool(); +} + +void Options::setCustomShownameEnabled(bool value) +{ + config.setValue("show_custom_shownames", value); +} + +QString Options::username() const +{ + return config.value("default_username", "").value<QString>(); +} + +void Options::setUsername(QString value) +{ + config.setValue("default_username", value); +} + +QString Options::shownameOnJoin() const +{ + return config.value("default_showname", "").toString(); +} + +void Options::setShownameOnJoin(QString value) +{ + config.setValue("default_showname", value); +} + +QString Options::audioOutputDevice() const +{ + return config.value("default_audio_device", "default").toString(); +} + +void Options::setAudioOutputDevice(QString value) +{ + config.setValue("default_audio_device", value); +} + +bool Options::blankBlip() const +{ + return config.value("blank_blip", false).toBool(); +} + +void Options::setBlankBlip(bool value) { config.setValue("blank_blip", value); } + +bool Options::loopingSfx() const +{ + return config.value("looping_sfx", true).toBool(); +} + +void Options::setLoopingSfx(bool value) +{ + config.setValue("looping_sfx", value); +} + +bool Options::objectionStopMusic() const +{ + return config.value("objection_stop_music", false).toBool(); +} + +void Options::setObjectionStopMusic(bool value) +{ + config.setValue("objection_stop_music", value); +} + +bool Options::streamingEnabled() const +{ + return config.value("streaming_enabled", true).toBool(); +} + +void Options::setStreamingEnabled(bool value) +{ + config.setValue("streaming_enabled", value); +} + +bool Options::objectionSkipQueueEnabled() const +{ + return config.value("instant_objection", true).toBool(); +} + +void Options::setObjectionSkipQueueEnabled(bool value) +{ + config.setValue("instant_objection", value); +} + +bool Options::desynchronisedLogsEnabled() const +{ + return config.value("desync_logs", false).toBool(); +} + +void Options::setDesynchronisedLogsEnabled(bool value) +{ + config.setValue("desync_logs", value); +} + +bool Options::discordEnabled() const +{ + return config.value("discord", true).toBool(); +} + +void Options::setDiscordEnabled(bool value) +{ + config.setValue("discord", value); +} + +bool Options::shakeEnabled() const +{ + return config.value("shake", true).toBool(); +} + +void Options::setShakeEnabled(bool value) { config.setValue("shake", value); } + +bool Options::effectsEnabled() const +{ + return config.value("effects", true).toBool(); +} + +void Options::setEffectsEnabled(bool value) +{ + config.setValue("effects", value); +} + +bool Options::networkedFrameSfxEnabled() const +{ + return config.value("framenetwork", true).toBool(); +} + +void Options::setNetworkedFrameSfxEnabled(bool value) +{ + config.setValue("framenetwork", value); +} + +bool Options::colorLogEnabled() const +{ + return config.value("colorlog", true).toBool(); +} + +void Options::setColorLogEnabled(bool value) +{ + config.setValue("colorlog", value); +} + +bool Options::clearSoundsDropdownOnPlayEnabled() const +{ + return config.value("stickysounds", true).toBool(); +} + +void Options::setClearSoundsDropdownOnPlayEnabled(bool value) +{ + config.setValue("stickysounds", value); +} + +bool Options::clearEffectsDropdownOnPlayEnabled() const +{ + return config.value("stickyeffects", true).toBool(); +} + +void Options::setClearEffectsDropdownOnPlayEnabled(bool value) +{ + config.setValue("stickyeffects", value); +} + +bool Options::clearPreOnPlayEnabled() const +{ + return config.value("stickypres", true).toBool(); +} + +void Options::setClearPreOnPlayEnabled(bool value) +{ + config.setValue("stickypres", value); +} + +bool Options::customChatboxEnabled() const +{ + return config.value("customchat", true).toBool(); +} + +void Options::setCustomChatboxEnabled(bool value) +{ + config.setValue("customchat", value); +} + +bool Options::characterStickerEnabled() const +{ + return config.value("sticker", true).toBool(); +} + +void Options::setCharacterStickerEnabled(bool value) +{ + config.setValue("sticker", value); +} + +bool Options::continuousPlaybackEnabled() const +{ + return config.value("continuous_playback", true).toBool(); +} + +void Options::setContinuousPlaybackEnabled(bool value) +{ + config.setValue("continuous_playback", value); +} + +bool Options::stopMusicOnCategoryEnabled() const +{ + return config.value("category_stop", true).toBool(); +} + +void Options::setStopMusicOnCategoryEnabled(bool value) +{ + config.setValue("category_stop", value); +} + +bool Options::logToTextFileEnabled() const +{ + return config.value("automatic_logging_enabled", true).toBool(); +} + +void Options::setLogToTextFileEnabled(bool value) +{ + config.setValue("automatic_logging_enabled", value); +} + +bool Options::logToDemoFileEnabled() const +{ + return config.value("demo_logging_enabled", true).toBool(); +} + +void Options::setLogToDemoFileEnabled(bool value) +{ + config.setValue("demo_logging_enabled", value); +} + +QString Options::subTheme() const +{ + if (settingsSubTheme() == "server" && !m_server_subtheme.isEmpty()) { + return m_server_subtheme; + } + return settingsSubTheme(); +} + +QString Options::settingsSubTheme() const +{ + return config.value("subtheme", "server").toString(); +} + +void Options::setSettingsSubTheme(QString value) +{ + config.setValue("subtheme", value); +} + +QString Options::serverSubTheme() const { return m_server_subtheme; } + +void Options::setServerSubTheme(QString value) { m_server_subtheme = value; } + +bool Options::animatedThemeEnabled() const +{ + return config.value("animated_theme", true).toBool(); +} + +void Options::setAnimatedThemeEnabled(bool value) +{ + config.setValue("animated_theme", value); +} + +QString Options::defaultScalingMode() const +{ + return config.value("default_scaling", "fast").toString(); +} + +void Options::setDefaultScalingMode(QString value) +{ + config.setValue("default_scaling", value); +} + +QStringList Options::mountPaths() const +{ + return config.value("mount_paths").value<QStringList>(); +} + +void Options::setMountPaths(QStringList value) +{ + config.setValue("mount_paths", value); +} + +bool Options::playerCountOptout() const +{ + return config.value("player_count_optout", false).toBool(); +} + +void Options::setPlayerCountOptout(bool value) +{ + config.setValue("player_count_optout", value); +} + +bool Options::playSelectedSFXOnIdle() const +{ + return config.value("sfx_on_idle", false).toBool(); +} + +void Options::setPlaySelectedSFXOnIdle(bool value) +{ + config.setValue("sfx_on_idle", value); +} + +bool Options::evidenceDoubleClickEdit() const +{ + return config.value("evidence_double_click", true).toBool(); +} + +void Options::setEvidenceDoubleClickEdit(bool value) +{ + config.setValue("evidence_double_click", value); +} + +QString Options::alternativeMasterserver() const +{ + return config.value("master", "").toString(); +} + +void Options::setAlternativeMasterserver(QString value) +{ + config.setValue("master", value); +} + +QString Options::language() const +{ + return config.value("language", QLocale::system().name()).toString(); +} + +void Options::setLanguage(QString value) { config.setValue("language", value); } + +QStringList Options::callwords() const +{ + QStringList l_callwords = + config.value("callwords", QStringList{}).toStringList(); + + // Please someone explain to me how tf I am supposed to create an empty + // QStringList using QSetting defaults. + if (l_callwords.size() == 1 && l_callwords.at(0).isEmpty()) + l_callwords.clear(); + return l_callwords; +} + +void Options::setCallwords(QStringList value) +{ + config.setValue("callwords", value); +} + +void Options::clearConfig() { config.clear(); } + +QVector<server_type> Options::favorites() +{ + QVector<server_type> serverlist; + + auto grouplist = favorite.childGroups(); + { // remove all negative and non-numbers + auto filtered_grouplist = grouplist; + for (const QString &group : qAsConst(grouplist)) { + bool ok = false; + const int l_num = group.toInt(&ok); + if (ok && l_num >= 0) { + continue; + } + filtered_grouplist.append(group); + } + std::sort(filtered_grouplist.begin(), filtered_grouplist.end(), + [](const auto &a, const auto &b) -> bool { + return a.toInt() < b.toInt(); + }); + grouplist = std::move(filtered_grouplist); + } + + for (const QString &group : qAsConst(grouplist)) { + server_type f_server; + favorite.beginGroup(group); + f_server.ip = favorite.value("address", "127.0.0.1").toString(); + f_server.port = favorite.value("port", 27016).toInt(); + f_server.name = favorite.value("name", "Missing Name").toString(); + f_server.desc = favorite.value("desc", "No description").toString(); + f_server.socket_type = + to_connection_type.value(favorite.value("protocol", "tcp").toString()); + serverlist.append(std::move(f_server)); + favorite.endGroup(); + } + + return serverlist; +} + +void Options::setFavorites(QVector<server_type> value) +{ + favorite.clear(); + for (int i = 0; i < value.size(); ++i) { + auto fav_server = value.at(i); + favorite.beginGroup(QString::number(i)); + favorite.setValue("name", fav_server.name); + favorite.setValue("address", fav_server.ip); + favorite.setValue("port", fav_server.port); + favorite.setValue("desc", fav_server.desc); + + if (fav_server.socket_type == TCP) { + favorite.setValue("protocol", "tcp"); + } + else { + favorite.setValue("protocol", "ws"); + } + favorite.endGroup(); + } + favorite.sync(); +} + +void Options::removeFavorite(int index) +{ + QVector<server_type> l_favorites = favorites(); + l_favorites.remove(index); + setFavorites(l_favorites); +} + +void Options::addFavorite(server_type server) +{ + int index = favorites().size(); + favorite.beginGroup(QString::number(index)); + favorite.setValue("name", server.name); + favorite.setValue("address", server.ip); + favorite.setValue("port", server.port); + favorite.setValue("desc", server.desc); + if (server.socket_type == TCP) { + favorite.setValue("protocol", "tcp"); + } + else { + favorite.setValue("protocol", "ws"); + } + favorite.endGroup(); + favorite.sync(); +} + +void Options::updateFavorite(server_type server, int index) +{ + favorite.beginGroup(QString::number(index)); + favorite.setValue("name", server.name); + favorite.setValue("address", server.ip); + favorite.setValue("port", server.port); + favorite.setValue("desc", server.desc); + if (server.socket_type == TCP) { + favorite.setValue("protocol", "tcp"); + } + else { + favorite.setValue("protocol", "ws"); + } + favorite.endGroup(); + favorite.sync(); +} + +QString Options::getUIAsset(QString f_asset_name) +{ + QStringList l_paths{":/base/themes/" + Options::getInstance().theme() + "/" + + f_asset_name}; + + if (subTheme() == "server") { + if (serverSubTheme().isEmpty()) { + l_paths.prepend(":/base/themes/" + theme() + "/" + serverSubTheme() + + "/" + f_asset_name); + } + } + else { + l_paths.prepend(":/base/themes/" + theme() + "/" + subTheme() + "/" + + f_asset_name); + } + + for (const QString &l_path : qAsConst(l_paths)) { + if (QFile::exists(l_path)) { + return l_path; + } + } + qWarning() << "Unable to locate ui-asset" << f_asset_name << "in theme" + << theme() << "Defaulting to embeeded asset."; + return QString(":/resource/ui/" + f_asset_name); +} diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index 9c05b65f..9bd4d8f6 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -5,10 +5,11 @@ #include "hardware_functions.h" #include "lobby.h" #include "networkmanager.h" +#include "options.h" void AOApplication::append_to_demofile(QString packet_string) { - if (get_demo_logging_enabled() && !log_filename.isEmpty()) + if (Options::getInstance().logToDemoFileEnabled() && !log_filename.isEmpty()) { QString path = log_filename.left(log_filename.size()).replace(".log", ".demo"); if (!demo_timer.isValid()) @@ -71,8 +72,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) client_id = f_contents.at(0).toInt(); server_software = f_contents.at(1); - if (lobby_constructed) - w_lobby->enable_connect_button(); + net_manager->server_connected(true); QStringList f_contents = {"AO2", get_version_string()}; send_server_packet(new AOPacket("ID", f_contents)); @@ -150,10 +150,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_lobby->set_server_description(f_contents.at(2)); } - if (w_lobby->doubleclicked) { - send_server_packet(new AOPacket("askchaa")); - w_lobby->doubleclicked = false; - } log_to_demo = false; } else if (header == "SI") { @@ -179,34 +175,39 @@ void AOApplication::server_packet_received(AOPacket *p_packet) courtroom_loaded = false; int selected_server = w_lobby->get_selected_server(); - QString server_address = "", server_name = ""; - if (w_lobby->public_servers_selected) { - if (selected_server >= 0 && selected_server < server_list.size()) { - auto info = server_list.at(selected_server); - server_name = info.name; - server_address = - QString("%1:%2").arg(info.ip, QString::number(info.port)); - window_title = server_name; - } + switch (w_lobby->pageSelected()) { + case 0: + if (selected_server >= 0 && selected_server < server_list.size()) { + auto info = server_list.at(selected_server); + server_name = info.name; + server_address = + QString("%1:%2").arg(info.ip, QString::number(info.port)); + window_title = server_name; + } + break; + case 1: + { + QVector<server_type> favorite_list = Options::getInstance().favorites(); + if (selected_server >= 0 && selected_server < favorite_list.size()) { + auto info = favorite_list.at(selected_server); + server_name = info.name; + server_address = + QString("%1:%2").arg(info.ip, QString::number(info.port)); + window_title = server_name; + } } - else { - if (selected_server >= 0 && selected_server < favorite_list.size()) { - auto info = favorite_list.at(selected_server); - server_name = info.name; - server_address = - QString("%1:%2").arg(info.ip, QString::number(info.port)); - window_title = server_name; - } + break; + case 2: + window_title = "Local Demo Recording"; + break; + default: + break; } if (courtroom_constructed) w_courtroom->set_window_title(window_title); - w_lobby->show_loading_overlay(); - w_lobby->set_loading_text(tr("Loading")); - w_lobby->set_loading_value(0); - AOPacket *f_packet; f_packet = new AOPacket("RC"); @@ -214,7 +215,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) // Remove any characters not accepted in folder names for the server_name // here - if (AOApplication::get_demo_logging_enabled() && server_name != "Demo playback") { + if (Options::getInstance().logToDemoFileEnabled() && server_name != "Demo playback") { this->log_filename = QDateTime::currentDateTime().toUTC().toString( "'logs/" + server_name.remove(QRegularExpression("[\\\\/:*?\"<>|\']")) + "/'yyyy-MM-dd hh-mm-ss t'.log'"); @@ -228,7 +229,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) QCryptographicHash hash(QCryptographicHash::Algorithm::Sha256); hash.addData(server_address.toUtf8()); - if (is_discord_enabled()) + if (Options::getInstance().discordEnabled()) discord->state_server(server_name.toStdString(), hash.result().toBase64().toStdString()); log_to_demo = false; @@ -264,21 +265,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet) f_char.taken = false; w_courtroom->append_char(f_char); - - if (!courtroom_loaded) { - ++loaded_chars; - w_lobby->set_loading_text(tr("Loading chars:\n%1/%2") - .arg(QString::number(loaded_chars)) - .arg(QString::number(char_list_size))); - - 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<double>(total_loading_size)) * - 100); - w_lobby->set_loading_value(loading_value); - } } if (!courtroom_loaded) @@ -295,11 +281,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet) for (int n_element = 0; n_element < f_contents.size(); ++n_element) { ++loaded_music; - - w_lobby->set_loading_text(tr("Loading music:\n%1/%2") - .arg(QString::number(loaded_music)) - .arg(QString::number(music_list_size))); - if (musics_time) { w_courtroom->append_music(f_contents.at(n_element)); } @@ -319,14 +300,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet) areas++; } } - - 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<double>(total_loading_size)) * - 100); - w_lobby->set_loading_value(loading_value); } for (int area_n = 0; area_n < areas; area_n++) { @@ -370,10 +343,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet) if (!courtroom_constructed) goto end; - if (lobby_constructed) - w_courtroom->append_server_chatmessage(tr("[Global log]"), - w_lobby->get_chatlog(), "0"); - w_courtroom->character_loading_finished(); w_courtroom->done_received(); @@ -534,13 +503,6 @@ void AOApplication::server_packet_received(AOPacket *p_packet) if (courtroom_constructed && !f_contents.isEmpty()) w_courtroom->mod_called(f_contents.at(0)); } - else if (header == "CASEA") { - if (courtroom_constructed && f_contents.size() >= 6) - w_courtroom->case_called(f_contents.at(0), f_contents.at(1) == "1", - f_contents.at(2) == "1", f_contents.at(3) == "1", - f_contents.at(4) == "1", - f_contents.at(5) == "1"); - } else if (header == "TI") { // Timer packet if (!courtroom_constructed || f_contents.size() < 2) goto end; @@ -603,14 +565,15 @@ void AOApplication::server_packet_received(AOPacket *p_packet) subtheme = f_contents.at(0); // Check if we have subthemes set to "server" - QString p_st = configini->value("subtheme").value<QString>(); - if (p_st.toLower() != "server") + if (Options::getInstance().settingsSubTheme().toLower() != "server") // We don't. Simply acknowledge the subtheme sent by the server, but don't do anything else. return; // Reload theme request - if (f_contents.size() > 1 && f_contents.at(1) == "1") + if (f_contents.size() > 1 && f_contents.at(1) == "1") { + Options::getInstance().setServerSubTheme(subtheme); w_courtroom->on_reload_theme_clicked(); + } } // Auth packet else if (header == "AUTH") { diff --git a/src/path_functions.cpp b/src/path_functions.cpp index 2128ad93..df76383d 100644 --- a/src/path_functions.cpp +++ b/src/path_functions.cpp @@ -1,6 +1,7 @@ #include "aoapplication.h" #include "courtroom.h" #include "file_functions.h" +#include "options.h" #include <QDir> #include <QRegularExpression> @@ -28,31 +29,10 @@ static bool is_power_2(unsigned int n) { return r == 1; } -QString AOApplication::get_base_path() -{ - QString base_path = ""; -#ifdef ANDROID - QString sdcard_storage = getenv("SECONDARY_STORAGE"); - if (dir_exists(sdcard_storage + "/base/")) { - base_path = sdcard_storage + "/base/"; - } - else { - QString external_storage = getenv("EXTERNAL_STORAGE"); - base_path = external_storage + "/base/"; - } -#elif defined(__APPLE__) - base_path = applicationDirPath() + "/../../../base/"; -#else - base_path = applicationDirPath() + "/base/"; -#endif - - return base_path; -} - VPath AOApplication::get_theme_path(QString p_file, QString p_theme) { if (p_theme == "") - p_theme = current_theme; + p_theme = Options::getInstance().theme(); return VPath("themes/" + p_theme + "/" + p_file); } @@ -280,9 +260,9 @@ QString AOApplication::get_sfx(QString p_sfx, QString p_misc, QString p_characte { QVector<VPath> pathlist; // Sounds subfolder is prioritized for organization sake - pathlist += get_asset_paths("sounds/" + p_sfx, current_theme, get_subtheme(), default_theme, p_misc, p_character); + pathlist += get_asset_paths("sounds/" + p_sfx, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, p_misc, p_character); // If sound subfolder not found, search just for SFX - pathlist += get_asset_paths(p_sfx, current_theme, get_subtheme(), default_theme, p_misc, p_character); + pathlist += get_asset_paths(p_sfx, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, p_misc, p_character); // If SFX not found, search base/sounds/general/ folder pathlist += get_sounds_path(p_sfx); QString ret = get_sfx_path(pathlist); @@ -346,7 +326,7 @@ QString AOApplication::get_real_path(const VPath &vpath, } // Cache miss; try all known mount paths - QStringList bases = get_mount_paths(); + QStringList bases = Options::getInstance().mountPaths(); bases.prepend(get_base_path()); // base // content 1 diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index f3dc0cb9..8aba93fd 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -1,147 +1,6 @@ #include "text_file_functions.h" #include "aoutils.h" - -QString AOApplication::read_theme() -{ - QString result = configini->value("theme", "default").value<QString>(); - return result; -} - -int AOApplication::read_blip_rate() -{ - int result = configini->value("blip_rate", 2).toInt(); - - if (result < 0) - return 0; - - return result; -} - -QString AOApplication::get_ooc_name() -{ - QString result = configini->value("ooc_name").value<QString>(); - return result; -} - -int AOApplication::get_default_music() -{ - int result = configini->value("default_music", 50).toInt(); - return result; -} - -int AOApplication::get_default_sfx() -{ - int result = configini->value("default_sfx", 50).toInt(); - return result; -} - -int AOApplication::get_default_blip() -{ - int result = configini->value("default_blip", 50).toInt(); - return result; -} - -int AOApplication::get_default_suppress_audio() -{ - int result = configini->value("suppress_audio", 50).toInt(); - return result; -} - -int AOApplication::get_max_log_size() -{ - int result = configini->value("log_maximum", 1000).toInt(); - return result; -} - -int AOApplication::stay_time() -{ - int result = configini->value("stay_time", 200).toInt(); - return result; -} - -int AOApplication::get_text_crawl() -{ - int result = configini->value("text_crawl", 40).toInt(); - return result; -} - -int AOApplication::get_chat_ratelimit() -{ - int result = configini->value("chat_ratelimit", 300).toInt(); - return result; -} - -bool AOApplication::get_log_goes_downwards() -{ - QString result = - configini->value("log_goes_downwards", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_log_newline() -{ - QString result = configini->value("log_newline", "false").value<QString>(); - return result.startsWith("true"); -} - -int AOApplication::get_log_margin() -{ - int result = configini->value("log_margin", 0).toInt(); - return result; -} - -bool AOApplication::get_log_timestamp() -{ - QString result = configini->value("log_timestamp", "false").value<QString>(); - return result.startsWith("true"); -} - -QString AOApplication::get_log_timestamp_format() -{ - QString result = configini->value("log_timestamp_format", "h:mm:ss AP").value<QString>(); - return result; -} - -bool AOApplication::get_log_ic_actions() -{ - QString result = - configini->value("log_ic_actions", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_showname_enabled_by_default() -{ - QString result = - configini->value("show_custom_shownames", "true").value<QString>(); - return result.startsWith("true"); -} - -QString AOApplication::get_default_username() -{ - QString result = configini->value("default_username", "").value<QString>(); - if (result.isEmpty()) - return get_ooc_name(); - else - return result; -} - -QString AOApplication::get_default_showname() -{ - QString result = configini->value("default_showname", "").value<QString>(); - return result; -} - -QString AOApplication::get_audio_output_device() -{ - QString result = - configini->value("default_audio_device", "default").value<QString>(); - return result; -} - -QStringList AOApplication::get_call_words() -{ - return get_list_file(get_base_path() + "callwords.ini"); -} +#include "options.h" QStringList AOApplication::get_list_file(VPath path) { @@ -202,6 +61,7 @@ bool AOApplication::write_to_file(QString p_text, QString p_file, bool make_dir) if (f_log.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { QTextStream out(&f_log); + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) out.setCodec("UTF-8"); #endif @@ -233,6 +93,7 @@ bool AOApplication::append_to_file(QString p_text, QString p_file, QFile f_log(p_file); if (f_log.open(QIODevice::WriteOnly | QIODevice::Append)) { QTextStream out(&f_log); + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) out.setCodec("UTF-8"); #endif @@ -245,101 +106,23 @@ bool AOApplication::append_to_file(QString p_text, QString p_file, return false; } -QVector<server_type> AOApplication::read_favorite_servers() +QMultiMap<QString, QString> AOApplication::load_demo_logs_list() const { - QVector<server_type> serverlist; - - // demo server is always at the top - server_type demo_server; - demo_server.ip = "127.0.0.1"; - demo_server.port = 99999; - demo_server.name = tr("Demo playback"); - demo_server.desc = tr("Play back demos you have previously recorded"); - serverlist.append(demo_server); - - QString fav_servers_ini_path(get_base_path() + "favorite_servers.ini"); - if (!QFile::exists(fav_servers_ini_path)) { - qWarning() << "failed to locate favorite_servers.ini, falling back to legacy serverlist.txt"; - serverlist += read_legacy_favorite_servers(); - } - else { - QSettings fav_servers_ini(fav_servers_ini_path, QSettings::IniFormat); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - fav_servers_ini.setIniCodec("UTF-8"); -#endif + QString l_log_path = applicationDirPath() + "/logs/"; + QDir l_log_folder(l_log_path); + l_log_folder.setFilter(QDir::NoDotAndDotDot | QDir::Dirs); - auto grouplist = fav_servers_ini.childGroups(); - { // remove all negative and non-numbers - auto filtered_grouplist = grouplist; - for (const QString &group : qAsConst(grouplist)) { - bool ok = false; - const int l_num = group.toInt(&ok); - if (ok && l_num >= 0) { - continue; - } - filtered_grouplist.append(group); - } - std::sort(filtered_grouplist.begin(), filtered_grouplist.end(), [](const auto &a, const auto &b) -> bool { - return a.toInt() < b.toInt(); - }); - grouplist = std::move(filtered_grouplist); - } + QMultiMap<QString,QString> l_demo_logs; + for (const QString &l_demo_folder_name : l_log_folder.entryList()) { + QDir l_demo_folder(l_log_path + l_demo_folder_name); + l_demo_folder.setFilter(QDir::Files); + l_demo_folder.setNameFilters(QStringList() << "*.demo"); - for(const QString &group: qAsConst(grouplist)) { - server_type f_server; - fav_servers_ini.beginGroup(group); - f_server.ip = fav_servers_ini.value("address", "127.0.0.1").toString(); - f_server.port = fav_servers_ini.value("port", 27016).toInt(); - f_server.name = fav_servers_ini.value("name", "Missing Name").toString(); - f_server.desc = fav_servers_ini.value("desc", "No description").toString(); - f_server.socket_type = to_connection_type.value(fav_servers_ini.value("protocol", "tcp").toString()); - serverlist.append(std::move(f_server)); - fav_servers_ini.endGroup(); - } - } - - return serverlist; -} - -QVector<server_type> AOApplication::read_legacy_favorite_servers() -{ - QVector<server_type> serverlist; - - QFile serverlist_txt(get_base_path() + "serverlist.txt"); - if (!serverlist_txt.exists()) { - qWarning() << "serverlist.txt does not exist"; - } else if (!serverlist_txt.open(QIODevice::ReadOnly)) { - qWarning() << "failed to open serverlist.txt"; - } else { - QTextStream stream(&serverlist_txt); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - stream.setCodec("UTF-8"); -#endif - - while (!stream.atEnd()) - { - QStringList contents = stream.readLine().split(":"); - - int item_count = contents.size(); - if (item_count < 3 || item_count > 4) { - continue; - } - - server_type server; - server.ip = contents.at(0); - server.port = contents.at(1).toInt(); - server.name = contents.at(2); - if (item_count == 4) { - server.socket_type = connection_type(contents.at(3).toInt()); - } else { - server.socket_type = TCP; - } - serverlist.append(std::move(server)); + for (QString l_demo_name : l_demo_folder.entryList()) { + l_demo_logs.insert(l_demo_folder_name, l_demo_name); + } } - serverlist_txt.close(); - } - - return serverlist; + return l_demo_logs; } QString AOApplication::read_design_ini(QString p_identifier, @@ -368,7 +151,7 @@ QString AOApplication::read_design_ini(QString p_identifier, Qt::TransformationMode AOApplication::get_scaling(QString p_scaling) { if (p_scaling.isEmpty()) - p_scaling = get_default_scaling(); + p_scaling = Options::getInstance().defaultScalingMode(); if (p_scaling == "smooth") return Qt::SmoothTransformation; @@ -377,7 +160,7 @@ Qt::TransformationMode AOApplication::get_scaling(QString p_scaling) QPoint AOApplication::get_button_spacing(QString p_identifier, QString p_file) { - QString value = get_config_value(p_identifier, p_file, current_theme, get_subtheme(), default_theme); + QString value = get_config_value(p_identifier, p_file, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme); QPoint return_value; return_value.setX(0); @@ -423,7 +206,7 @@ pos_size_type AOApplication::get_element_dimensions(QString p_identifier, QString AOApplication::get_design_element(QString p_identifier, QString p_file, QString p_misc) { - QString value = get_config_value(p_identifier, p_file, current_theme, get_subtheme(), default_theme, p_misc); + QString value = get_config_value(p_identifier, p_file, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, p_misc); if (!value.isEmpty()) return value; return ""; @@ -432,7 +215,7 @@ QString AOApplication::get_design_element(QString p_identifier, QString p_file, // tfw this function is only used for lobby and nowhere else int AOApplication::get_font_size(QString p_identifier, QString p_file) { - QString value = get_config_value(p_identifier, p_file, current_theme, get_subtheme(), default_theme); + QString value = get_config_value(p_identifier, p_file, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme); if (!value.isEmpty()) return value.toInt(); return 10; @@ -440,7 +223,7 @@ int AOApplication::get_font_size(QString p_identifier, QString p_file) QColor AOApplication::get_color(QString p_identifier, QString p_file) { - QString value = get_config_value(p_identifier, p_file, current_theme, get_subtheme(), default_theme); + QString value = get_config_value(p_identifier, p_file, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme); QColor return_color(0, 0, 0); if (value.isEmpty()) @@ -460,7 +243,7 @@ QColor AOApplication::get_color(QString p_identifier, QString p_file) QString AOApplication::get_stylesheet(QString p_file) { - QString path = get_asset(p_file, current_theme, get_subtheme(), default_theme); + QString path = get_asset(p_file, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme); QFile design_ini; design_ini.setFileName(path); if (!design_ini.open(QIODevice::ReadOnly)) @@ -480,7 +263,7 @@ QString AOApplication::get_stylesheet(QString p_file) QString AOApplication::get_tagged_stylesheet(QString target_tag, QString p_file) { - QString path = get_asset(p_file, current_theme, get_subtheme(), default_theme); + QString path = get_asset(p_file, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme); QFile design_ini; design_ini.setFileName(path); if (!design_ini.open(QIODevice::ReadOnly)) @@ -514,7 +297,7 @@ QString AOApplication::get_tagged_stylesheet(QString target_tag, QString p_file) QString AOApplication::get_chat_markup(QString p_identifier, QString p_chat) { // New Chadly method - QString value = get_config_value(p_identifier, "chat_config.ini", current_theme, get_subtheme(), default_theme, p_chat); + QString value = get_config_value(p_identifier, "chat_config.ini", Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, p_chat); if (!value.isEmpty()) return value.toUtf8(); @@ -557,14 +340,14 @@ QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat) QString AOApplication::get_penalty_value(QString p_identifier) { - return get_config_value(p_identifier, "penalty/penalty.ini", current_theme, - get_subtheme(), default_theme, ""); + return get_config_value(p_identifier, "penalty/penalty.ini", Options::getInstance().theme(), + Options::getInstance().subTheme(), default_theme, ""); } QString AOApplication::get_court_sfx(QString p_identifier, QString p_misc) { - QString value = get_config_value(p_identifier, "courtroom_sounds.ini", current_theme, get_subtheme(), default_theme, p_misc); + QString value = get_config_value(p_identifier, "courtroom_sounds.ini", Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, p_misc); if (!value.isEmpty()) return value.toUtf8(); return ""; @@ -615,10 +398,10 @@ QString AOApplication::read_char_ini(QString p_char, QString p_search_line, { QSettings settings(get_real_path(get_character_path(p_char, "char.ini")), QSettings::IniFormat); - settings.beginGroup(target_tag); #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) settings.setIniCodec("UTF-8"); #endif + settings.beginGroup(target_tag); QString value = settings.value(p_search_line).value<QString>(); settings.endGroup(); return value; @@ -629,6 +412,7 @@ void AOApplication::set_char_ini(QString p_char, QString value, { QSettings settings(get_real_path(get_character_path(p_char, "char.ini")), QSettings::IniFormat); + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) settings.setIniCodec("UTF-8"); #endif @@ -927,8 +711,8 @@ int AOApplication::get_text_delay(QString p_char, QString p_emote) QStringList AOApplication::get_effects(QString p_char) { const QStringList l_filepath_list{ - get_asset("effects/effects.ini", current_theme, get_subtheme(), default_theme, ""), - get_asset("effects.ini", current_theme, get_subtheme(), default_theme, read_char_ini(p_char, "effects", "Options")), + get_asset("effects/effects.ini", Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, ""), + get_asset("effects.ini", Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, read_char_ini(p_char, "effects", "Options")), }; QStringList l_effect_name_list; @@ -943,7 +727,6 @@ QStringList AOApplication::get_effects(QString p_char) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) l_effects_ini.setIniCodec("UTF-8"); #endif - // port legacy effects if (!l_effects_ini.contains("version/major") || l_effects_ini.value("version/major").toInt() < 2) { @@ -998,8 +781,8 @@ QString AOApplication::get_effect(QString effect, QString p_char, p_folder = read_char_ini(p_char, "effects", "Options"); QStringList paths { - get_image("effects/" + effect, current_theme, get_subtheme(), default_theme, ""), - get_image(effect, current_theme, get_subtheme(), default_theme, p_folder) + get_image("effects/" + effect, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, ""), + get_image(effect, Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, p_folder) }; for (const auto &p : paths) @@ -1014,8 +797,8 @@ QString AOApplication::get_effect_property(QString fx_name, QString p_char, if (p_folder == "") p_folder = read_char_ini(p_char, "effects", "Options"); - const auto paths = get_asset_paths("effects/effects.ini", current_theme, get_subtheme(), default_theme, ""); - const auto misc_paths = get_asset_paths("effects.ini", current_theme, get_subtheme(), default_theme, p_folder); + const auto paths = get_asset_paths("effects/effects.ini", Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, ""); + const auto misc_paths = get_asset_paths("effects.ini", Options::getInstance().theme(), Options::getInstance().subTheme(), default_theme, p_folder); QString path; QString f_result; for (const VPath &p : paths + misc_paths) { @@ -1060,230 +843,3 @@ bool AOApplication::get_pos_is_judge(const QString &p_pos) } return positions.contains(p_pos.trimmed()); } - -bool AOApplication::get_blank_blip() -{ - QString result = configini->value("blank_blip", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_looping_sfx() -{ - QString result = configini->value("looping_sfx", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::objection_stop_music() -{ - QString result = - configini->value("objection_stop_music", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_streaming_disabled() -{ - return configini->value("streaming_disabled", false).toBool(); -} - -bool AOApplication::is_instant_objection_enabled() -{ - QString result = configini->value("instant_objection", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_desyncrhonized_logs_enabled() -{ - QString result = configini->value("desync_logs", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_discord_enabled() -{ - QString result = configini->value("discord", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_shake_enabled() -{ - QString result = configini->value("shake", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_effects_enabled() -{ - QString result = configini->value("effects", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_frame_network_enabled() -{ - QString result = configini->value("framenetwork", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_colorlog_enabled() -{ - QString result = configini->value("colorlog", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_stickysounds_enabled() -{ - QString result = configini->value("stickysounds", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_stickyeffects_enabled() -{ - QString result = configini->value("stickyeffects", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_stickypres_enabled() -{ - QString result = configini->value("stickypres", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_customchat_enabled() -{ - QString result = configini->value("customchat", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_sticker_enabled() -{ - QString result = configini->value("sticker", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_continuous_enabled() -{ - QString result = configini->value("continuous_playback", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::is_category_stop_enabled() -{ - QString result = configini->value("category_stop", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_casing_enabled() -{ - QString result = configini->value("casing_enabled", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_casing_defence_enabled() -{ - QString result = - configini->value("casing_defence_enabled", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_casing_prosecution_enabled() -{ - QString result = - configini->value("casing_prosecution_enabled", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_casing_judge_enabled() -{ - QString result = - configini->value("casing_judge_enabled", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_casing_juror_enabled() -{ - QString result = - configini->value("casing_juror_enabled", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_casing_steno_enabled() -{ - QString result = - configini->value("casing_steno_enabled", "false").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_casing_cm_enabled() -{ - QString result = - configini->value("casing_cm_enabled", "false").value<QString>(); - return result.startsWith("true"); -} - -QString AOApplication::get_casing_can_host_cases() -{ - QString result = - configini->value("casing_can_host_cases", "Turnabout Check Your Settings") - .value<QString>(); - return result; -} - -bool AOApplication::get_text_logging_enabled() -{ - QString result = - configini->value("automatic_logging_enabled", "true").value<QString>(); - return result.startsWith("true"); -} - -bool AOApplication::get_demo_logging_enabled() -{ - QString result = - configini->value("demo_logging_enabled", "true").value<QString>(); - return result.startsWith("true"); -} - -QString AOApplication::get_subtheme() -{ - QString result = - configini->value("subtheme", "server").value<QString>(); - // Server means we want the server to decide for us - if (result == "server") - // 'subtheme' variable is affected by the server - result = subtheme; - // Default means we don't want any subthemes - else if (result == "default") - result = ""; - return result; -} - -bool AOApplication::get_animated_theme() -{ - QString result = - configini->value("animated_theme", "false").value<QString>(); - return result.startsWith("true"); -} - -QString AOApplication::get_default_scaling() -{ - return configini->value("default_scaling", "fast").value<QString>(); -} - -QStringList AOApplication::get_mount_paths() -{ - return configini->value("mount_paths").value<QStringList>(); -} - -bool AOApplication::get_player_count_optout() -{ - return configini->value("player_count_optout", "false").value<QString>() - .startsWith("true"); -} - -bool AOApplication::get_sfx_on_idle() -{ - return configini->value("sfx_on_idle", "true").value<QString>() - .startsWith("true"); -} - -bool AOApplication::get_evidence_double_click() -{ - return configini->value("evidence_double_click", "false").value<QString>() - .startsWith("true"); -} diff --git a/src/widgets/add_server_dialog.cpp b/src/widgets/add_server_dialog.cpp new file mode 100644 index 00000000..d590d77c --- /dev/null +++ b/src/widgets/add_server_dialog.cpp @@ -0,0 +1,96 @@ +#include "widgets/add_server_dialog.h" +#include "datatypes.h" +#include "options.h" + +#include <QComboBox> +#include <QDebug> +#include <QDialogButtonBox> +#include <QFile> +#include <QLineEdit> +#include <QLabel> +#include <QPlainTextEdit> +#include <QPushButton> +#include <QSpinBox> +#include <QUiLoader> +#include <QVBoxLayout> + +#define FROM_UI(type, name) \ + ; \ + ui_##name = findChild<type *>(#name); + +AddServerDialog::AddServerDialog() +{ + QUiLoader l_loader(this); + QFile l_uiFile(Options::getInstance().getUIAsset(DEFAULT_UI)); + + if (!l_uiFile.open(QFile::ReadOnly)) { + qCritical() << "Unable to open file " << l_uiFile.fileName(); + return; + } + ui_widget = l_loader.load(&l_uiFile, this); + + auto l_layout = new QVBoxLayout(this); + l_layout->addWidget(ui_widget); + + FROM_UI(QLineEdit, server_display_name_edit); + FROM_UI(QLineEdit, server_hostname_edit); + FROM_UI(QSpinBox, server_port_box); + FROM_UI(QComboBox, server_protocol_box); + FROM_UI(QPlainTextEdit, server_description_edit); + FROM_UI(QDialogButtonBox, server_dialog_button); + connect(ui_server_dialog_button, &QDialogButtonBox::accepted, this, + &::AddServerDialog::onSavePressed); + connect(ui_server_dialog_button, &QDialogButtonBox::rejected, this, + &AddServerDialog::onCancelPressed); + + FROM_UI(QLabel, server_legacy_lbl); + FROM_UI(QLineEdit, server_legacy_edit); + FROM_UI(QPushButton, server_legacy_load_button); + connect(ui_server_legacy_load_button, &QPushButton::released, this, + &AddServerDialog::parseLegacyServerEntry); +} + +void AddServerDialog::onSavePressed() +{ + server_type server; + server.name = ui_server_display_name_edit->text(); + server.ip = ui_server_hostname_edit->text(); + server.port = ui_server_port_box->value(); + server.desc = ui_server_description_edit->toPlainText(); + server.socket_type = + ui_server_protocol_box->currentIndex() == TCP_INDEX ? TCP : WEBSOCKETS; + Options::getInstance().addFavorite(server); + close(); +} + +void AddServerDialog::onCancelPressed() +{ + close(); + deleteLater(); +} + +void AddServerDialog::parseLegacyServerEntry() +{ + QStringList l_legacy_entry = ui_server_legacy_edit->text().split(":"); + server_type l_server_entry; + if (l_legacy_entry.isEmpty()) { + qDebug() << "Legacy entry empty."; + return; + } + + int l_item_count = l_legacy_entry.size(); + + if (l_item_count >= 3) { + ui_server_hostname_edit->setText(l_legacy_entry.at(0)); + ui_server_port_box->setValue(l_legacy_entry.at(1).toInt()); + ui_server_display_name_edit->setText(l_legacy_entry.at(2)); + if (l_item_count >= 4) { + if (l_legacy_entry.at(3) == "ws") { + ui_server_protocol_box->setCurrentIndex(1); + } + else { + ui_server_protocol_box->setCurrentIndex(0); + } + } + } +} diff --git a/src/widgets/aooptionsdialog.cpp b/src/widgets/aooptionsdialog.cpp new file mode 100644 index 00000000..8b7befe9 --- /dev/null +++ b/src/widgets/aooptionsdialog.cpp @@ -0,0 +1,648 @@ +#include "widgets/aooptionsdialog.h" +#include "QDesktopServices" +#include "aoapplication.h" +#include "bass.h" +#include "file_functions.h" +#include "networkmanager.h" +#include "options.h" + +#include <QCheckBox> +#include <QCollator> +#include <QComboBox> +#include <QDialogButtonBox> +#include <QGroupBox> +#include <QLabel> +#include <QLineEdit> +#include <QPlainTextEdit> +#include <QPushButton> +#include <QResource> +#include <QSpinBox> +#include <QUiLoader> +#include <QVBoxLayout> + +#define FROM_UI(type, name) \ + ; \ + ui_##name = findChild<type *>(#name); + +AOOptionsDialog::AOOptionsDialog(QDialog *parent, AOApplication *p_ao_app) + : QDialog(parent) +{ + ao_app = p_ao_app; + setupUI(); +} + +void AOOptionsDialog::populateAudioDevices() +{ + ui_audio_device_combobox->clear(); + if (needsDefaultAudioDevice()) { + ui_audio_device_combobox->addItem("default"); + } + + BASS_DEVICEINFO info; + for (int a = 0; BASS_GetDeviceInfo(a, &info); a++) { + ui_audio_device_combobox->addItem(info.name); + } +} + +template <> +void AOOptionsDialog::setWidgetData(QCheckBox *widget, const bool &value) +{ + widget->setChecked(value); +} + +template <> bool AOOptionsDialog::widgetData(QCheckBox *widget) const +{ + return widget->isChecked(); +} + +template <> +void AOOptionsDialog::setWidgetData(QLineEdit *widget, const QString &value) +{ + widget->setText(value); +} + +template <> QString AOOptionsDialog::widgetData(QLineEdit *widget) const +{ + return widget->text(); +} + +template <> +void AOOptionsDialog::setWidgetData(QLineEdit *widget, const uint16_t &value) +{ + widget->setText(QString::number(value)); +} + +template <> uint16_t AOOptionsDialog::widgetData(QLineEdit *widget) const +{ + return widget->text().toUShort(); +} + +template <> +void AOOptionsDialog::setWidgetData(QPlainTextEdit *widget, + const QStringList &value) +{ + widget->setPlainText(value.join('\n')); +} + +template <> +QStringList AOOptionsDialog::widgetData(QPlainTextEdit *widget) const +{ + return widget->toPlainText().trimmed().split('\n'); +} + +template <> +void AOOptionsDialog::setWidgetData(QSpinBox *widget, const int &value) +{ + widget->setValue(value); +} + +template <> int AOOptionsDialog::widgetData(QSpinBox *widget) const +{ + return widget->value(); +} + +template <> +void AOOptionsDialog::setWidgetData(QComboBox *widget, const QString &value) +{ + for (auto i = 0; i < widget->count(); i++) { + if (widget->itemText(i) == value) { + widget->setCurrentIndex(i); + return; + } + } + qWarning() << "value" << value << "not found for widget" + << widget->objectName(); +} + +template <> QString AOOptionsDialog::widgetData(QComboBox *widget) const +{ + return widget->currentText(); +} + +template <> +void AOOptionsDialog::setWidgetData(QGroupBox *widget, const bool &value) +{ + widget->setChecked(value); +} + +template <> bool AOOptionsDialog::widgetData(QGroupBox *widget) const +{ + return widget->isChecked(); +} + +template <> +void AOOptionsDialog::setWidgetData(QListWidget *widget, + const QStringList &value) +{ + widget->addItems(value); +} + +template <> QStringList AOOptionsDialog::widgetData(QListWidget *widget) const +{ + QStringList paths; + for (auto i = 1; i < widget->count(); i++) { + paths.append(widget->item(i)->text()); + } + return paths; +} + +template <typename T, typename V> +void AOOptionsDialog::registerOption(const QString &widgetName, + V (Options::*getter)() const, + void (Options::*setter)(V)) +{ + auto *widget = findChild<T *>(widgetName); + if (!widget) { + qWarning() << "could not find widget" << widgetName; + return; + } + + OptionEntry entry; + entry.load = [=] { + setWidgetData<T, V>(widget, (Options::getInstance().*getter)()); + }; + entry.save = [=] { + (Options::getInstance().*setter)(widgetData<T, V>(widget)); + }; + + optionEntries.append(entry); +} + +void AOOptionsDialog::updateValues() +{ + QSet<QString> themes; + QStringList bases = Options::getInstance().mountPaths(); + bases.push_front(get_base_path()); + + for (const QString &base : bases) { + QStringList l_themes = + QDir(base + "themes").entryList(QDir::Dirs | QDir::NoDotAndDotDot); + + // Resorts list to match numeric sorting found in Windows. + QCollator l_sorting; + l_sorting.setNumericMode(true); + std::sort(l_themes.begin(), l_themes.end(), l_sorting); + + for (const QString &l_theme : qAsConst(l_themes)) { + if (!themes.contains(l_theme)) { + ui_theme_combobox->addItem(l_theme); + themes.insert(l_theme); + } + } + } + + QStringList l_subthemes = + QDir(ao_app->get_real_path(ao_app->get_theme_path(""))) + .entryList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const QString &l_subtheme : qAsConst(l_subthemes)) { + if (l_subtheme.toLower() != "server" && l_subtheme.toLower() != "default" && + l_subtheme.toLower() != "effects" && l_subtheme.toLower() != "misc") { + ui_subtheme_combobox->addItem(l_subtheme); + } + } + + ao_app->net_manager->request_document( + MSDocumentType::PrivacyPolicy, [this](QString document) { + if (document.isEmpty()) { + document = tr("Couldn't get the privacy policy."); + } + ui_privacy_policy->setHtml(document); + }); + + for (const OptionEntry &entry : qAsConst(optionEntries)) { + entry.load(); + } +} + +void AOOptionsDialog::savePressed() +{ + bool l_reload_theme_required = (ui_theme_combobox->currentText() != Options::getInstance().theme()); + for (const OptionEntry &entry : qAsConst(optionEntries)) { + entry.save(); + } + + if (l_reload_theme_required) { + emit reloadThemeRequest(); + } + close(); +} + +void AOOptionsDialog::discardPressed() { close(); } + +void AOOptionsDialog::buttonClicked(QAbstractButton *button) +{ + if (ui_settings_buttons->buttonRole(button) == QDialogButtonBox::ResetRole) { + if (QMessageBox::question( + this, "", "Restore default settings?\nThis can't be undone!", + QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { + // Destructive operation. + Options::getInstance().clearConfig(); + updateValues(); + } + } +} + +void AOOptionsDialog::onReloadThemeClicked() +{ + Options::getInstance().setTheme(ui_theme_combobox->currentText()); + Options::getInstance().setSettingsSubTheme(ui_subtheme_combobox->currentText()); + Options::getInstance().setAnimatedThemeEnabled( + ui_animated_theme_cb->isChecked()); + emit reloadThemeRequest(); + delete layout(); + delete ui_settings_widget; + optionEntries.clear(); + setupUI(); +} + +void AOOptionsDialog::themeChanged(int i) +{ + ui_subtheme_combobox->clear(); + // Fill the combobox with the names of the themes. + ui_subtheme_combobox->addItem("server"); + ui_subtheme_combobox->addItem("default"); + + QStringList l_subthemes = QDir(ao_app->get_real_path(ao_app->get_theme_path( + "", ui_theme_combobox->itemText(i)))) + .entryList(QDir::Dirs | QDir::NoDotAndDotDot); + + for (const QString &l_subthemes : qAsConst(l_subthemes)) { + if (l_subthemes.toLower() != "server" && + l_subthemes.toLower() != "default" && + l_subthemes.toLower() != "effects" && l_subthemes.toLower() != "misc") { + ui_subtheme_combobox->addItem(l_subthemes); + } + } + + QString l_ressource_name = Options::getInstance().theme() + ".rcc"; + QString l_resource = + ao_app->get_asset("themes/" + ui_theme_combobox->currentText() + ".rcc"); + if (l_resource.isEmpty()) { + QResource::unregisterResource( + ao_app->get_asset("themes/" + l_ressource_name)); + qDebug() << "Unable to locate ressource file" << l_ressource_name; + return; + } + QResource::registerResource(l_resource); +} + +void AOOptionsDialog::setupUI() +{ + QUiLoader l_loader(this); + QFile l_uiFile(Options::getInstance().getUIAsset("options_dialog.ui")); + if (!l_uiFile.open(QFile::ReadOnly)) { + qWarning() << "Unable to open file " << l_uiFile.fileName(); + return; + } + + ui_settings_widget = l_loader.load(&l_uiFile, this); + + auto l_layout = new QVBoxLayout(this); + l_layout->addWidget(ui_settings_widget); + + // General dialog element. + FROM_UI(QDialogButtonBox, settings_buttons); + + connect(ui_settings_buttons, &QDialogButtonBox::accepted, this, + &AOOptionsDialog::savePressed); + connect(ui_settings_buttons, &QDialogButtonBox::rejected, this, + &AOOptionsDialog::discardPressed); + connect(ui_settings_buttons, &QDialogButtonBox::clicked, this, + &AOOptionsDialog::buttonClicked); + + // Gameplay Tab + FROM_UI(QComboBox, theme_combobox) + connect(ui_theme_combobox, + QOverload<int>::of(&QComboBox::currentIndexChanged), this, + &AOOptionsDialog::themeChanged); + + registerOption<QComboBox, QString>("theme_combobox", &Options::theme, + &Options::setTheme); + + FROM_UI(QComboBox, subtheme_combobox) + registerOption<QComboBox, QString>("subtheme_combobox", &Options::settingsSubTheme, + &Options::setSettingsSubTheme); + + FROM_UI(QPushButton, theme_reload_button) + connect(ui_theme_reload_button, &QPushButton::clicked, this, + &::AOOptionsDialog::onReloadThemeClicked); + + FROM_UI(QPushButton, theme_folder_button) + connect(ui_theme_folder_button, &QPushButton::clicked, this, [=] { + QString p_path = ao_app->get_real_path(ao_app->get_theme_path( + "", ui_theme_combobox->itemText(ui_theme_combobox->currentIndex()))); + if (!dir_exists(p_path)) { + return; + } + QDesktopServices::openUrl(QUrl::fromLocalFile(p_path)); + }); + + FROM_UI(QCheckBox, animated_theme_cb) + FROM_UI(QSpinBox, stay_time_spinbox) + FROM_UI(QCheckBox, instant_objection_cb) + FROM_UI(QSpinBox, text_crawl_spinbox) + FROM_UI(QSpinBox, chat_ratelimit_spinbox) + FROM_UI(QLineEdit, username_textbox) + FROM_UI(QCheckBox, showname_cb) + FROM_UI(QLineEdit, default_showname_textbox) + FROM_UI(QLineEdit, ms_textbox) + FROM_UI(QCheckBox, discord_cb) + FROM_UI(QComboBox, language_combobox) + FROM_UI(QComboBox, scaling_combobox) + FROM_UI(QCheckBox, shake_cb) + FROM_UI(QCheckBox, effects_cb) + FROM_UI(QCheckBox, framenetwork_cb) + FROM_UI(QCheckBox, colorlog_cb) + FROM_UI(QCheckBox, stickysounds_cb) + FROM_UI(QCheckBox, stickyeffects_cb) + FROM_UI(QCheckBox, stickypres_cb) + FROM_UI(QCheckBox, customchat_cb) + FROM_UI(QCheckBox, sticker_cb) + FROM_UI(QCheckBox, continuous_cb) + FROM_UI(QCheckBox, category_stop_cb) + FROM_UI(QCheckBox, sfx_on_idle_cb) + FROM_UI(QCheckBox, evidence_double_click_cb) + + registerOption<QCheckBox, bool>("animated_theme_cb", + &Options::animatedThemeEnabled, + &Options::setAnimatedThemeEnabled); + registerOption<QSpinBox, int>("stay_time_spinbox", &Options::textStayTime, + &Options::setTextStayTime); + registerOption<QCheckBox, bool>("instant_objection_cb", + &Options::objectionSkipQueueEnabled, + &Options::setObjectionSkipQueueEnabled); + registerOption<QSpinBox, int>("text_crawl_spinbox", &Options::textCrawlSpeed, + &Options::setTextCrawlSpeed); + registerOption<QSpinBox, int>("chat_ratelimit_spinbox", + &Options::chatRateLimit, + &Options::setChatRateLimit); + registerOption<QLineEdit, QString>("username_textbox", &Options::username, + &Options::setUsername); + registerOption<QCheckBox, bool>("showname_cb", + &Options::customShownameEnabled, + &Options::setCustomShownameEnabled); + registerOption<QLineEdit, QString>("default_showname_textbox", + &Options::shownameOnJoin, + &Options::setShownameOnJoin); + registerOption<QLineEdit, QString>("ms_textbox", + &Options::alternativeMasterserver, + &Options::setAlternativeMasterserver); + registerOption<QCheckBox, bool>("discord_cb", &Options::discordEnabled, + &Options::setDiscordEnabled); + registerOption<QComboBox, QString>("language_combobox", &Options::language, + &Options::setLanguage); + registerOption<QComboBox, QString>("scaling_combobox", + &Options::defaultScalingMode, + &Options::setDefaultScalingMode); + + // Populate scaling dropdown. This is necessary as we need the user data + // embeeded into the entry. + ui_scaling_combobox->addItem(tr("Pixel"), "fast"); + ui_scaling_combobox->addItem(tr("Smooth"), "smooth"); + + registerOption<QCheckBox, bool>("shake_cb", &Options::shakeEnabled, + &Options::setShakeEnabled); + registerOption<QCheckBox, bool>("effects_cb", &Options::effectsEnabled, + &Options::setEffectsEnabled); + registerOption<QCheckBox, bool>("framenetwork_cb", + &Options::networkedFrameSfxEnabled, + &Options::setNetworkedFrameSfxEnabled); + registerOption<QCheckBox, bool>("colorlog_cb", &Options::colorLogEnabled, + &Options::setColorLogEnabled); + registerOption<QCheckBox, bool>( + "stickysounds_cb", &Options::clearSoundsDropdownOnPlayEnabled, + &Options::setClearSoundsDropdownOnPlayEnabled); + registerOption<QCheckBox, bool>( + "stickyeffects_cb", &Options::clearEffectsDropdownOnPlayEnabled, + &Options::setClearEffectsDropdownOnPlayEnabled); + registerOption<QCheckBox, bool>("stickypres_cb", + &Options::clearPreOnPlayEnabled, + &Options::setClearPreOnPlayEnabled); + registerOption<QCheckBox, bool>("customchat_cb", + &Options::customChatboxEnabled, + &Options::setCustomChatboxEnabled); + registerOption<QCheckBox, bool>("sticker_cb", + &Options::characterStickerEnabled, + &Options::setCharacterStickerEnabled); + registerOption<QCheckBox, bool>("continuous_cb", + &Options::continuousPlaybackEnabled, + &Options::setContinuousPlaybackEnabled); + registerOption<QCheckBox, bool>("category_stop_cb", + &Options::stopMusicOnCategoryEnabled, + &Options::setStopMusicOnCategoryEnabled); + registerOption<QCheckBox, bool>("sfx_on_idle_cb", + &Options::playSelectedSFXOnIdle, + &Options::setPlaySelectedSFXOnIdle); + registerOption<QCheckBox, bool>("evidence_double_click_cb", + &Options::evidenceDoubleClickEdit, + &Options::setEvidenceDoubleClickEdit); + + // Callwords tab. This could just be a QLineEdit, but no, we decided to allow + // people to put a billion entries in. + FROM_UI(QPlainTextEdit, callwords_textbox) + registerOption<QPlainTextEdit, QStringList>( + "callwords_textbox", &Options::callwords, &Options::setCallwords); + + // Audio tab. + FROM_UI(QComboBox, audio_device_combobox) + populateAudioDevices(); + registerOption<QComboBox, QString>("audio_device_combobox", + &Options::audioOutputDevice, + &Options::setAudioOutputDevice); + + FROM_UI(QSpinBox, suppress_audio_spinbox) + FROM_UI(QSpinBox, bliprate_spinbox) + FROM_UI(QCheckBox, blank_blips_cb) + FROM_UI(QCheckBox, loopsfx_cb) + FROM_UI(QCheckBox, objectmusic_cb) + FROM_UI(QCheckBox, disablestreams_cb) + + registerOption<QSpinBox, int>("suppress_audio_spinbox", + &::Options::defaultSuppressAudio, + &Options::setDefaultSupressedAudio); + registerOption<QSpinBox, int>("bliprate_spinbox", &::Options::blipRate, + &Options::setBlipRate); + registerOption<QCheckBox, bool>("blank_blips_cb", &Options::blankBlip, + &Options::setBlankBlip); + registerOption<QCheckBox, bool>("loopsfx_cb", &Options::loopingSfx, + &Options::setLoopingSfx); + registerOption<QCheckBox, bool>("objectmusic_cb", + &Options::objectionStopMusic, + &Options::setObjectionStopMusic); + registerOption<QCheckBox, bool>("disablestreams_cb", + &Options::streamingEnabled, + &Options::setStreamingEnabled); + + // Asset tab + FROM_UI(QListWidget, mount_list) + auto *defaultMount = + new QListWidgetItem(tr("%1 (default)").arg(get_base_path())); + defaultMount->setFlags(Qt::ItemFlag::NoItemFlags); + ui_mount_list->addItem(defaultMount); + registerOption<QListWidget, QStringList>("mount_list", &Options::mountPaths, + &Options::setMountPaths); + + FROM_UI(QPushButton, mount_add) + connect(ui_mount_add, &QPushButton::clicked, this, [this] { + QString path = QFileDialog::getExistingDirectory( + this, tr("Select a base folder"), QApplication::applicationDirPath(), + QFileDialog::ShowDirsOnly); + if (path.isEmpty()) { + return; + } + QDir dir(QApplication::applicationDirPath()); + QString relative = dir.relativeFilePath(path); + if (!relative.contains("../")) { + path = relative; + } + QListWidgetItem *dir_item = new QListWidgetItem(path); + ui_mount_list->addItem(dir_item); + ui_mount_list->setCurrentItem(dir_item); + + // quick hack to update buttons + emit ui_mount_list->itemSelectionChanged(); + }); + + FROM_UI(QPushButton, mount_remove) + connect(ui_mount_remove, &QPushButton::clicked, this, [this] { + auto selected = ui_mount_list->selectedItems(); + if (selected.isEmpty()) return; + delete selected[0]; + emit ui_mount_list->itemSelectionChanged(); + asset_cache_dirty = true; + }); + + FROM_UI(QPushButton, mount_up) + connect(ui_mount_up, &QPushButton::clicked, this, [this] { + auto selected = ui_mount_list->selectedItems(); + if (selected.isEmpty()) return; + auto *item = selected[0]; + int row = ui_mount_list->row(item); + ui_mount_list->takeItem(row); + int new_row = qMax(1, row - 1); + ui_mount_list->insertItem(new_row, item); + ui_mount_list->setCurrentRow(new_row); + asset_cache_dirty = true; + }); + + FROM_UI(QPushButton, mount_down) + connect(ui_mount_down, &QPushButton::clicked, this, [this] { + auto selected = ui_mount_list->selectedItems(); + if (selected.isEmpty()) return; + auto *item = selected[0]; + int row = ui_mount_list->row(item); + ui_mount_list->takeItem(row); + int new_row = qMin(ui_mount_list->count() + 1, row + 1); + ui_mount_list->insertItem(new_row, item); + ui_mount_list->setCurrentRow(new_row); + asset_cache_dirty = true; + }); + + FROM_UI(QPushButton, mount_clear_cache) + connect(ui_mount_clear_cache, &QPushButton::clicked, this, [this] { + asset_cache_dirty = true; + ui_mount_clear_cache->setEnabled(false); + }); + + connect(ui_mount_list, &QListWidget::itemSelectionChanged, this, [this] { + auto selected_items = ui_mount_list->selectedItems(); + bool row_selected = !ui_mount_list->selectedItems().isEmpty(); + ui_mount_remove->setEnabled(row_selected); + ui_mount_up->setEnabled(row_selected); + ui_mount_down->setEnabled(row_selected); + + if (!row_selected) return; + + int row = ui_mount_list->row(selected_items[0]); + if (row <= 1) ui_mount_up->setEnabled(false); + if (row >= ui_mount_list->count() - 1) ui_mount_down->setEnabled(false); + }); + + // Logging tab + FROM_UI(QCheckBox, downwards_cb) + FROM_UI(QSpinBox, length_spinbox) + FROM_UI(QCheckBox, log_newline_cb) + FROM_UI(QSpinBox, log_margin_spinbox) + FROM_UI(QLabel, log_timestamp_format_lbl) + FROM_UI(QComboBox, log_timestamp_format_combobox) + + registerOption<QCheckBox, bool>("downwards_cb", + &Options::logDirectionDownwards, + &Options::setLogDirectionDownwards); + registerOption<QSpinBox, int>("length_spinbox", &Options::maxLogSize, + &Options::setMaxLogSize); + registerOption<QCheckBox, bool>("log_newline_cb", &Options::logNewline, + &Options::setLogNewline); + registerOption<QSpinBox, int>("log_margin_spinbox", &Options::logMargin, + &Options::setLogMargin); + + FROM_UI(QCheckBox, log_timestamp_cb) + registerOption<QCheckBox, bool>("log_timestamp_cb", + &Options::logTimestampEnabled, + &Options::setLogTimestampEnabled); + connect(ui_log_timestamp_cb, &QCheckBox::stateChanged, this, + &::AOOptionsDialog::timestampCbChanged); + ui_log_timestamp_format_lbl->setText( + tr("Log timestamp format:\n") + + QDateTime::currentDateTime().toString( + Options::getInstance().logTimestampFormat())); + + FROM_UI(QComboBox, log_timestamp_format_combobox) + registerOption<QComboBox, QString>("log_timestamp_format_combobox", + &Options::logTimestampFormat, + &Options::setLogTimestampFormat); + connect(ui_log_timestamp_format_combobox, &QComboBox::currentTextChanged, + this, &::AOOptionsDialog::onTimestampFormatEdited); + + QString l_current_format = Options::getInstance().logTimestampFormat(); + + ui_log_timestamp_format_combobox->setCurrentText(l_current_format); + + if (!Options::getInstance().logTimestampEnabled()) { + ui_log_timestamp_format_combobox->setDisabled(true); + } + + FROM_UI(QCheckBox, log_ic_actions_cb) + FROM_UI(QCheckBox, desync_logs_cb) + FROM_UI(QCheckBox, log_text_cb) + + registerOption<QCheckBox, bool>("log_ic_actions_cb", &Options::logIcActions, + &Options::setLogIcActions); + registerOption<QCheckBox, bool>("desync_logs_cb", + &Options::desynchronisedLogsEnabled, + &Options::setDesynchronisedLogsEnabled); + registerOption<QCheckBox, bool>("log_text_cb", &Options::logToTextFileEnabled, + &Options::setLogToTextFileEnabled); + registerOption<QCheckBox, bool>("log_demo_cb", &Options::logToDemoFileEnabled, + &Options::setLogToDemoFileEnabled); + + // DSGVO/Privacy tab + + FROM_UI(QTextBrowser, privacy_policy) + ui_privacy_policy->setPlainText(tr("Getting privacy policy...")); + + updateValues(); +} + +void AOOptionsDialog::onTimestampFormatEdited() +{ + ui_log_timestamp_format_lbl->setText( + tr("Log timestamp format:\n") + + QDateTime::currentDateTime().toString( + ui_log_timestamp_format_combobox->currentText())); +} + +void AOOptionsDialog::timestampCbChanged(int state) +{ + ui_log_timestamp_format_combobox->setDisabled(state == 0); +} + +#if (defined(_WIN32) || defined(_WIN64)) +bool AOOptionsDialog::needsDefaultAudioDevice() { return true; } +#elif (defined(LINUX) || defined(__linux__)) +bool AOOptionsDialog::needsDefaultAudioDevice() { return false; } +#elif defined __APPLE__ +bool AOOptionsDialog::needsDefaultAudioDevice() { return true; } +#else +#error This operating system is not supported. +#endif diff --git a/src/widgets/direct_connect_dialog.cpp b/src/widgets/direct_connect_dialog.cpp new file mode 100644 index 00000000..82eaa23a --- /dev/null +++ b/src/widgets/direct_connect_dialog.cpp @@ -0,0 +1,101 @@ +#include "widgets/direct_connect_dialog.h" + +#include "networkmanager.h" +#include "options.h" +#include "debug_functions.h" + +#include <QComboBox> +#include <QLabel> +#include <QLineEdit> +#include <QPushButton> +#include <QSpinBox> +#include <QUiLoader> +#include <QVBoxLayout> +#include <QRegularExpressionMatch> +#include <QStringBuilder> +#include <QUrl> + +#define FROM_UI(type, name) \ + ; \ + ui_##name = findChild<type *>(#name); + +DirectConnectDialog::DirectConnectDialog(NetworkManager *p_net_manager) : + net_manager(p_net_manager) +{ + QUiLoader l_loader(this); + QFile l_uiFile(Options::getInstance().getUIAsset(DEFAULT_UI)); + + if (!l_uiFile.open(QFile::ReadOnly)) { + qCritical() << "Unable to open file " << l_uiFile.fileName(); + return; + } + ui_widget = l_loader.load(&l_uiFile, this); + + auto l_layout = new QVBoxLayout(this); + l_layout->addWidget(ui_widget); + + FROM_UI(QLineEdit, direct_hostname_edit) + + FROM_UI(QLabel, direct_connection_status_lbl) + + FROM_UI(QPushButton, direct_connect_button); + connect(ui_direct_connect_button, &QPushButton::pressed, + this, &DirectConnectDialog::onConnectPressed); + FROM_UI(QPushButton, direct_cancel_button); + connect(ui_direct_cancel_button, &QPushButton::pressed, + this, &DirectConnectDialog::close); + + connect(net_manager, &NetworkManager::server_connected, + this, &DirectConnectDialog::onServerConnected); + + connect(&connect_timeout, &QTimer::timeout, this, + &DirectConnectDialog::onConnectTimeout); + connect_timeout.setSingleShot(true); +} + +void DirectConnectDialog::onConnectPressed() +{ + QString l_hostname = ui_direct_hostname_edit->text(); + if (!SCHEME_PATTERN.match(l_hostname).hasMatch()) { + l_hostname = "tcp://" % l_hostname; + } + QUrl l_url(l_hostname); + if (!l_url.isValid()) { + call_error(tr("Invalid URL.")); + return; + } + if (!to_connection_type.contains(l_url.scheme())) { + call_error(tr("Scheme not recognized. Must be either of the following: ") % QStringList::fromVector(to_connection_type.keys().toVector()).join(", ")); + return; + } + if (l_url.port() == -1) { + call_error(tr("Invalid server port.")); + return; + } + server_type l_server; + l_server.socket_type = to_connection_type[l_url.scheme()]; + l_server.ip = l_url.host(); + l_server.port = l_url.port(); + l_server.name = "Direct Connection"; + + net_manager->connect_to_server(l_server); + ui_direct_connect_button->setEnabled(false); + ui_direct_connection_status_lbl->setText("Connecting..."); + ui_direct_connection_status_lbl->setStyleSheet("color : rgb(0,64,156)"); + connect_timeout.start(CONNECT_TIMEOUT); +} + +void DirectConnectDialog::onServerConnected() +{ + net_manager->join_to_server(); + ui_direct_connection_status_lbl->setText("Connected!"); + ui_direct_connection_status_lbl->setStyleSheet("color: rgb(0,128,0)"); + close(); +} + +void DirectConnectDialog::onConnectTimeout() +{ + ui_direct_connect_button->setEnabled(true); + ui_direct_connection_status_lbl->setText("Connection Timeout!"); + ui_direct_connection_status_lbl->setStyleSheet("color: rgb(255,0,0)"); +} diff --git a/src/widgets/edit_server_dialog.cpp b/src/widgets/edit_server_dialog.cpp new file mode 100644 index 00000000..109e968f --- /dev/null +++ b/src/widgets/edit_server_dialog.cpp @@ -0,0 +1,87 @@ +#include "widgets/edit_server_dialog.h" +#include "datatypes.h" +#include "options.h" + +#include <QComboBox> +#include <QDebug> +#include <QDialogButtonBox> +#include <QFile> +#include <QLineEdit> +#include <QLabel> +#include <QPlainTextEdit> +#include <QPushButton> +#include <QSpinBox> +#include <QUiLoader> +#include <QVBoxLayout> + +#define FROM_UI(type, name) \ + ; \ + ui_##name = findChild<type *>(#name); + +EditServerDialog::EditServerDialog(int index) : + index(index) // lol +{ + QUiLoader l_loader(this); + QFile l_uiFile(Options::getInstance().getUIAsset(DEFAULT_UI)); + + if (!l_uiFile.open(QFile::ReadOnly)) { + qCritical() << "Unable to open file " << l_uiFile.fileName(); + return; + } + ui_widget = l_loader.load(&l_uiFile, this); + + auto l_layout = new QVBoxLayout(this); + l_layout->addWidget(ui_widget); + + FROM_UI(QLineEdit, server_display_name_edit); + FROM_UI(QLineEdit, server_hostname_edit); + FROM_UI(QSpinBox, server_port_box); + FROM_UI(QComboBox, server_protocol_box); + FROM_UI(QPlainTextEdit, server_description_edit); + FROM_UI(QDialogButtonBox, server_dialog_button); + connect(ui_server_dialog_button, &QDialogButtonBox::accepted, this, + &::EditServerDialog::onSavePressed); + connect(ui_server_dialog_button, &QDialogButtonBox::rejected, this, + &EditServerDialog::onCancelPressed); + + // We don't need you. + FROM_UI(QLabel, server_legacy_lbl); + FROM_UI(QLineEdit, server_legacy_edit); + FROM_UI(QPushButton, server_legacy_load_button); + + ui_server_legacy_lbl->setVisible(false); + ui_server_legacy_edit->setVisible(false); + ui_server_legacy_load_button->setVisible(false); + + loadEntry(); +} + +void EditServerDialog::loadEntry() +{ + server_type server = Options::getInstance().favorites().at(index); + ui_server_display_name_edit->setText(server.name); + ui_server_hostname_edit->setText(server.ip); + ui_server_port_box->setValue(server.port); + ui_server_description_edit->setPlainText(server.desc); + ui_server_protocol_box->setCurrentIndex(server.socket_type); +} + +void EditServerDialog::onSavePressed() +{ + server_type server; + server.name = ui_server_display_name_edit->text(); + server.ip = ui_server_hostname_edit->text(); + server.port = ui_server_port_box->value(); + server.desc = ui_server_description_edit->toPlainText(); + server.socket_type = + ui_server_protocol_box->currentIndex() == TCP_INDEX ? TCP : WEBSOCKETS; + Options::getInstance().updateFavorite(server, index); + close(); + deleteLater(); +} + +void EditServerDialog::onCancelPressed() +{ + close(); + deleteLater(); +} |
