Merge branch 'master' into feature/http-ms

This commit is contained in:
oldmud0 2021-12-18 22:34:04 -06:00
commit b0e9f8dbe5
38 changed files with 1007 additions and 828 deletions

View File

@ -19,6 +19,9 @@ QMAKE_LFLAGS += -Wl,-rpath,"'\$$ORIGIN/lib'"
# Uncomment for verbose network logging
# DEFINES += DEBUG_NETWORK
# Uncomment for verbose animation logging
# DEFINES += DEBUG_MOVIE
# Uncomment for building with debug symbols
# CONFIG += debug

View File

@ -10,13 +10,11 @@ aoevidencebutton.h
aoevidencedisplay.h
aoimage.h
aolayer.h
aolineedit.h
aomusicplayer.h
aooptionsdialog.h
aopacket.h
aosfxplayer.h
aotextarea.h
aotextedit.h
bass.h
bassopus.h
chatlogpiece.h
@ -28,6 +26,7 @@ discord-rpc.h
discord_register.h
discord_rich_presence.h
discord_rpc.h
eventfilters.h
file_functions.h
hardware_functions.h
lobby.h

View File

@ -1,8 +1,6 @@
#ifndef AOAPPLICATION_H
#define AOAPPLICATION_H
#define UNUSED(x) (void)(x)
#include "aopacket.h"
#include "datatypes.h"
#include "demoserver.h"
@ -37,6 +35,25 @@ class NetworkManager;
class Lobby;
class Courtroom;
class VPath : QString {
using QString::QString;
public:
explicit VPath(const QString &str) : QString(str) {}
inline QString const &toQString() const { return *this; }
inline bool operator==(const VPath &str) const {
return this->toQString() == str.toQString();
}
inline VPath operator+(const VPath &str) const {
return VPath(this->toQString() + str.toQString());
}
};
inline uint qHash(const VPath &key, uint seed = qGlobalQHashSeed())
{
return qHash(key.toQString(), seed);
}
class AOApplication : public QApplication {
Q_OBJECT
@ -129,24 +146,26 @@ public:
// implementation in path_functions.cpp
QString get_base_path();
QString get_data_path();
QString get_theme_path(QString p_file, QString p_theme="");
QString get_character_path(QString p_char, QString p_file);
QString get_misc_path(QString p_misc, QString p_file);
QString get_sounds_path(QString p_file);
QString get_music_path(QString p_song);
QString get_background_path(QString p_file);
QString get_default_background_path(QString p_file);
QString get_evidence_path(QString p_file);
QStringList get_asset_paths(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="");
QString get_asset_path(QStringList pathlist);
QString get_image_path(QStringList pathlist, bool static_image=false);
QString get_sfx_path(QStringList pathlist);
VPath get_theme_path(QString p_file, QString p_theme="");
VPath get_character_path(QString p_char, QString p_file);
VPath get_misc_path(QString p_misc, QString p_file);
VPath get_sounds_path(QString p_file);
VPath get_music_path(QString p_song);
VPath get_background_path(QString p_file);
VPath get_default_background_path(QString p_file);
VPath get_evidence_path(QString p_file);
QVector<VPath> get_asset_paths(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="");
QString get_asset_path(QVector<VPath> pathlist);
QString get_image_path(QVector<VPath> pathlist, bool static_image=false);
QString get_sfx_path(QVector<VPath> pathlist);
QString get_config_value(QString p_identifier, QString p_config, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="");
QString get_asset(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="");
QString get_image(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="");
QString get_image(QString p_element, QString p_theme="", QString p_subtheme="", QString p_default_theme="", QString p_misc="", QString p_character="", QString p_placeholder="", bool static_image=false);
QString get_sfx(QString p_sfx, QString p_misc="", QString p_character="");
QString get_case_sensitive_path(QString p_file);
QString get_real_path(const VPath &vpath);
QString get_real_suffixed_path(const VPath &vpath, const QStringList &suffixes);
void invalidate_lookup_cache();
////// Functions for reading and writing files //////
// Implementations file_functions.cpp
@ -265,6 +284,9 @@ public:
// Returns whether the log should have a timestamp.
bool get_log_timestamp();
// Returns the format string for the log timestamp
QString get_log_timestamp_format();
// Returns whether to log IC actions.
bool get_log_ic_actions();
@ -284,6 +306,7 @@ public:
QStringList get_call_words();
// returns all of the file's lines in a QStringList
QStringList get_list_file(VPath path);
QStringList get_list_file(QString p_file);
// Process a file and return its text as a QString
@ -307,6 +330,7 @@ public:
QVector<server_type> read_serverlist_txt();
// Returns the value of p_identifier in the design.ini file in p_design_path
QString read_design_ini(QString p_identifier, VPath p_design_path);
QString read_design_ini(QString p_identifier, QString p_design_path);
// Returns the coordinates of widget with p_identifier from p_file
@ -336,18 +360,18 @@ public:
QString get_court_sfx(QString p_identifier, QString p_misc="");
// Figure out if we can opus this or if we should fall back to wav
QString get_sfx_suffix(QString sound_to_check);
QString get_sfx_suffix(VPath sound_to_check);
// Can we use APNG for this? If not, WEBP? If not, GIF? If not, fall back to
// PNG.
QString get_image_suffix(QString path_to_check, bool static_image=false);
QString get_image_suffix(VPath path_to_check, bool static_image=false);
// Returns the value of p_search_line within target_tag and terminator_tag
QString read_char_ini(QString p_char, QString p_search_line,
QString target_tag);
// Returns a QStringList of all key=value definitions on a given tag.
QStringList read_ini_tags(QString p_file, QString target_tag = "");
QStringList read_ini_tags(VPath p_file, QString target_tag = "");
// Sets the char.ini p_search_line key under tag target_tag to value.
void set_char_ini(QString p_char, QString value, QString p_search_line,
@ -491,6 +515,9 @@ public:
// Get the default scaling method
QString get_default_scaling();
// Get a list of custom mount paths
QStringList get_mount_paths();
// Get whether to opt out of player count metrics sent to the master server
bool get_player_count_optout();
@ -529,6 +556,9 @@ private:
QVector<server_type> server_list;
QVector<server_type> favorite_list;
QHash<uint, QString> asset_lookup_cache;
QHash<uint, QString> dir_listing_cache;
QSet<uint> dir_listing_exist_cache;
public slots:
void server_disconnected();

View File

@ -7,8 +7,12 @@
#include <QLabel>
#include <QTimer>
#include <QBitmap>
#include <QtConcurrent/QtConcurrentRun>
#include <QMutex>
#include <QWaitCondition>
class AOApplication;
class VPath;
// "Brief" explanation of what the hell this is:
//
@ -138,6 +142,18 @@ protected:
// Center the QLabel in the viewport based on the dimensions of f_pixmap
void center_pixmap(QPixmap f_pixmap);
private:
// Populates the frame and delay vectors.
void populate_vectors();
// used in populate_vectors
void load_next_frame();
bool exit_loop; //awful solution but i'm not fucking using QThread
QFuture<void> frame_loader;
QMutex mutex;
QWaitCondition frameAdded;
signals:
void done();
@ -235,4 +251,5 @@ public:
StickerLayer(QWidget *p_parent, AOApplication *p_ao_app);
void load_image(QString p_charname);
};
#endif // AOLAYER_H

View File

@ -1,26 +0,0 @@
#ifndef AOLINEEDIT_H
#define AOLINEEDIT_H
#include <QLineEdit>
#include <QMouseEvent>
class AOLineEdit : public QLineEdit {
Q_OBJECT
public:
AOLineEdit(QWidget *parent);
void preserve_selection(bool toggle) { p_selection = toggle; }
private:
bool p_selection = false;
protected:
void mouseDoubleClickEvent(QMouseEvent *e);
void focusOutEvent(QFocusEvent *ev);
signals:
void double_clicked();
};
#endif // AOLINEEDIT_H

View File

@ -23,6 +23,7 @@
#include <QtWidgets/QWidget>
#include <QDirIterator>
#include <QListWidget>
#include <QTextBrowser>
#include <QTextStream>
@ -62,6 +63,8 @@ private:
QSpinBox *ui_log_margin_spinbox;
QLabel *ui_log_timestamp_lbl;
QCheckBox *ui_log_timestamp_cb;
QLabel *ui_log_timestamp_format_lbl;
QComboBox *ui_log_timestamp_format_combobox;
QLabel *ui_stay_time_lbl;
QSpinBox *ui_stay_time_spinbox;
QLabel *ui_desync_logs_lbl;
@ -175,12 +178,25 @@ private:
QLabel *ui_log_lbl;
QCheckBox *ui_log_cb;
QWidget *ui_assets_tab;
QVBoxLayout *ui_assets_tab_layout;
QGridLayout *ui_mount_buttons_layout;
QLabel *ui_asset_lbl;
QListWidget *ui_mount_list;
QPushButton *ui_mount_add;
QPushButton *ui_mount_remove;
QPushButton *ui_mount_up;
QPushButton *ui_mount_down;
QPushButton *ui_mount_clear_cache;
QWidget *ui_privacy_tab;
QVBoxLayout *ui_privacy_layout;
QCheckBox *ui_privacy_optout_cb;
QFrame *ui_privacy_separator;
QTextBrowser *ui_privacy_policy;
bool asset_cache_dirty = false;
bool needs_default_audiodev();
void update_values();
@ -190,6 +206,8 @@ public slots:
void save_pressed();
void discard_pressed();
void button_clicked(QAbstractButton *button);
void on_timestamp_format_edited();
void timestamp_cb_changed(int state);
void on_reload_theme_clicked();
void theme_changed(int i);
};

View File

@ -1,21 +0,0 @@
#ifndef AOTEXTEDIT_H
#define AOTEXTEDIT_H
#include <QPlainTextEdit>
class AOTextEdit : public QPlainTextEdit {
Q_OBJECT
public:
AOTextEdit(QWidget *parent);
protected:
void mouseDoubleClickEvent(QMouseEvent *e);
signals:
void double_clicked();
private slots:
void on_enter_pressed();
};
#endif // AOTEXTEDIT_H

View File

@ -11,13 +11,11 @@
#include "aoevidencedisplay.h"
#include "aoimage.h"
#include "aolayer.h"
#include "aolineedit.h"
#include "aomusicplayer.h"
#include "aooptionsdialog.h"
#include "aopacket.h"
#include "aosfxplayer.h"
#include "aotextarea.h"
#include "aotextedit.h"
#include "chatlogpiece.h"
#include "datatypes.h"
#include "debug_functions.h"
@ -25,6 +23,7 @@
#include "hardware_functions.h"
#include "lobby.h"
#include "scrolltext.h"
#include "eventfilters.h"
#include <QCheckBox>
#include <QCloseEvent>
@ -417,6 +416,9 @@ private:
// True, if the log should have a timestamp.
bool log_timestamp = false;
// format string for aforementioned log timestamp
QString log_timestamp_format;
// How long in miliseconds should the objection wait before appearing.
int objection_threshold = 1500;
@ -648,7 +650,8 @@ private:
QComboBox *ui_pair_order_dropdown;
AOLineEdit *ui_ic_chat_message;
QLineEdit *ui_ic_chat_message;
AOLineEditFilter *ui_ic_chat_message_filter;
QLineEdit *ui_ic_chat_name;
QLineEdit *ui_ooc_chat_message;
@ -730,7 +733,8 @@ private:
AOButton *ui_evidence_button;
AOImage *ui_evidence;
AOLineEdit *ui_evidence_name;
QLineEdit *ui_evidence_name;
AOLineEditFilter *ui_evidence_name_filter;
QWidget *ui_evidence_buttons;
QVector<AOEvidenceButton *> ui_evidence_list;
AOButton *ui_evidence_left;
@ -738,7 +742,8 @@ private:
AOButton *ui_evidence_present;
AOImage *ui_evidence_overlay;
AOButton *ui_evidence_delete;
AOLineEdit *ui_evidence_image_name;
QLineEdit *ui_evidence_image_name;
AOLineEditFilter *ui_evidence_image_name_filter;
AOButton *ui_evidence_image_button;
AOButton *ui_evidence_x;
AOButton *ui_evidence_ok;
@ -746,7 +751,9 @@ private:
AOButton *ui_evidence_transfer;
AOButton *ui_evidence_save;
AOButton *ui_evidence_load;
AOTextEdit *ui_evidence_description;
AOButton *ui_evidence_edit;
QPlainTextEdit *ui_evidence_description;
AOImage *ui_char_select_background;
@ -873,6 +880,7 @@ private slots:
void on_evidence_image_button_clicked();
void on_evidence_clicked(int p_id);
void on_evidence_double_clicked(int p_id);
void on_evidence_edit_clicked();
void on_evidence_hover(int p_id, bool p_state);
@ -928,8 +936,6 @@ private slots:
void on_showname_enable_clicked();
void on_evidence_name_double_clicked();
void on_evidence_image_name_double_clicked();
void on_evidence_button_clicked();
void on_evidence_delete_clicked();

36
include/eventfilters.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef EVENTFILTERS_H
#define EVENTFILTERS_H
#include <QEvent>
#include <QLineEdit>
class AOLineEditFilter : public QObject
{
Q_OBJECT
public:
bool preserve_selection = false;
protected:
bool eventFilter(QObject *obj, QEvent *event) override {
QLineEdit *lineEdit = qobject_cast<QLineEdit *>(obj);
if (event->type() == QEvent::FocusOut && lineEdit != nullptr && preserve_selection) { // lost focus
int start = lineEdit->selectionStart();
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
int len = lineEdit->selectionLength();
#else
int len = lineEdit->selectedText().length();
#endif
if (start != -1 && len != -1) {
lineEdit->setSelection(start, len);\
return true;
}
}
return false;
}
signals:
void double_clicked();
};
#endif // EVENTFILTERS_H

View File

@ -86,7 +86,7 @@ private:
QProgressBar *ui_progress_bar;
AOButton *ui_cancel;
int last_index;
int last_index = -1;
void set_size_and_pos(QWidget *p_widget, QString p_identifier);

View File

@ -10,13 +10,11 @@ aoevidencebutton.cpp
aoevidencedisplay.cpp
aoimage.cpp
aolayer.cpp
aolineedit.cpp
aomusicplayer.cpp
aooptionsdialog.cpp
aopacket.cpp
aosfxplayer.cpp
aotextarea.cpp
aotextedit.cpp
charselect.cpp
chatlogpiece.cpp
courtroom.cpp

View File

@ -17,6 +17,8 @@ AOApplication::AOApplication(int &argc, char **argv) : QApplication(argc, argv)
net_manager = new NetworkManager(this);
discord = new AttorneyOnline::Discord();
qApp->setStyleSheet("QFrame {background-color:transparent;} QAbstractItemView {background-color: transparent; color: black;}; QLineEdit {background-color:transparent;}");
asset_lookup_cache.reserve(2048);
}
AOApplication::~AOApplication()
@ -164,13 +166,14 @@ void AOApplication::call_announce_menu(Courtroom *court)
}
// Callback for when BASS device is lost
// Only actually used for music syncs
void CALLBACK AOApplication::BASSreset(HSTREAM handle, DWORD channel,
DWORD data, void *user)
{
UNUSED(handle);
UNUSED(channel);
UNUSED(data);
UNUSED(user);
Q_UNUSED(handle);
Q_UNUSED(channel);
Q_UNUSED(data);
Q_UNUSED(user);
doBASSreset();
}
@ -183,6 +186,7 @@ void AOApplication::doBASSreset()
void AOApplication::initBASS()
{
BASS_SetConfig(BASS_CONFIG_DEV_DEFAULT, 1);
BASS_Free();
// Change the default audio output device to be the one the user has given
// in his config.ini file for now.

View File

@ -34,12 +34,6 @@ void AOBlipPlayer::blip_tick()
HSTREAM f_stream = m_stream_list[f_cycle];
BASS_ChannelSetDevice(f_stream, BASS_GetDevice());
int f_bass_error = BASS_ErrorGetCode();
if (f_bass_error == BASS_ERROR_DEVICE) {
ao_app->doBASSreset();
BASS_ChannelSetDevice(f_stream, BASS_GetDevice());
}
BASS_ChannelPlay(f_stream, false);
}

View File

@ -20,14 +20,9 @@ void AOButton::set_image(QString p_path, QString p_misc)
{
movie->stop();
QString p_image;
// Check if the user wants animated themes
if (ao_app->get_animated_theme())
// We want an animated image
p_image = ao_app->get_image(p_path, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_misc);
else
// Grab a static variant of the image
p_image = ao_app->get_image_path(ao_app->get_asset_paths(p_path, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_misc), true);
if (!file_exists(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());
if (p_image.isEmpty()) {
this->setIcon(QIcon());
this->setIconSize(this->size());
this->setStyleSheet("");

View File

@ -23,10 +23,10 @@ AOCaseAnnouncerDialog::AOCaseAnnouncerDialog(QWidget *parent,
ui_announcer_buttons->setStandardButtons(QDialogButtonBox::Ok |
QDialogButtonBox::Cancel);
QObject::connect(ui_announcer_buttons, SIGNAL(accepted()), this,
SLOT(ok_pressed()));
QObject::connect(ui_announcer_buttons, SIGNAL(rejected()), this,
SLOT(cancel_pressed()));
connect(ui_announcer_buttons, &QDialogButtonBox::accepted, this,
&AOCaseAnnouncerDialog::ok_pressed);
connect(ui_announcer_buttons, &QDialogButtonBox::rejected, this,
&AOCaseAnnouncerDialog::cancel_pressed);
setUpdatesEnabled(false);

View File

@ -11,7 +11,7 @@ AOEmoteButton::AOEmoteButton(QWidget *p_parent, AOApplication *p_ao_app,
this->move(p_x, p_y);
this->resize(p_w, p_h);
connect(this, SIGNAL(clicked()), this, SLOT(on_clicked()));
connect(this, &AOEmoteButton::clicked, this, &AOEmoteButton::on_clicked);
}
void AOEmoteButton::set_image(QString p_image, QString p_emote_comment)
@ -67,4 +67,4 @@ void AOEmoteButton::set_char_image(QString p_char, int p_emote, QString suffix)
this->set_image(image_path, ao_app->get_emote_comment(p_char, p_emote));
}
void AOEmoteButton::on_clicked() { emote_clicked(m_id); }
void AOEmoteButton::on_clicked() { emit emote_clicked(m_id); }

View File

@ -27,12 +27,12 @@ AOEvidenceButton::AOEvidenceButton(QWidget *p_parent, AOApplication *p_ao_app,
this->resize(p_w, p_h);
// this->setAcceptDrops(true);
connect(this, SIGNAL(clicked()), this, SLOT(on_clicked()));
connect(this, &AOEvidenceButton::clicked, this, &AOEvidenceButton::on_clicked);
}
void AOEvidenceButton::set_image(QString p_image)
{
QString image_path = ao_app->get_evidence_path(p_image);
QString image_path = ao_app->get_real_path(ao_app->get_evidence_path(p_image));
if (file_exists(p_image)) {
this->setText("");
this->setStyleSheet(
@ -57,8 +57,10 @@ void AOEvidenceButton::set_image(QString p_image)
void AOEvidenceButton::set_theme_image(QString p_image)
{
QString theme_image_path = ao_app->get_theme_path(p_image);
QString default_image_path = ao_app->get_theme_path(p_image, ao_app->default_theme);
QString theme_image_path = ao_app->get_real_path(
ao_app->get_theme_path(p_image));
QString default_image_path = ao_app->get_real_path(
ao_app->get_theme_path(p_image, ao_app->default_theme));
QString final_image_path;
@ -78,12 +80,12 @@ void AOEvidenceButton::set_selected(bool p_selected)
ui_selected->hide();
}
void AOEvidenceButton::on_clicked() { evidence_clicked(m_id); }
void AOEvidenceButton::on_clicked() { emit evidence_clicked(m_id); }
void AOEvidenceButton::mouseDoubleClickEvent(QMouseEvent *e)
{
QPushButton::mouseDoubleClickEvent(e);
evidence_double_clicked(m_id);
emit evidence_double_clicked(m_id);
}
/*
@ -106,7 +108,7 @@ void AOEvidenceButton::enterEvent(QEvent *e)
{
ui_selector->show();
on_hover(m_id, true);
emit on_hover(m_id, true);
setFlat(false);
QPushButton::enterEvent(e);
@ -116,6 +118,6 @@ void AOEvidenceButton::leaveEvent(QEvent *e)
{
ui_selector->hide();
on_hover(m_id, false);
emit on_hover(m_id, false);
QPushButton::leaveEvent(e);
}

View File

@ -13,7 +13,7 @@ AOEvidenceDisplay::AOEvidenceDisplay(QWidget *p_parent, AOApplication *p_ao_app)
evidence_movie = new InterfaceLayer(this, ao_app);
connect(evidence_movie, SIGNAL(done()), this, SLOT(show_done()));
connect(evidence_movie, &InterfaceLayer::done, this, &AOEvidenceDisplay::show_done);
}
void AOEvidenceDisplay::show_evidence(QString p_evidence_image,
@ -35,7 +35,8 @@ void AOEvidenceDisplay::show_evidence(QString p_evidence_image,
gif_name = "evidence_appear_right";
}
QString f_evidence_path = ao_app->get_evidence_path(p_evidence_image);
QString f_evidence_path = ao_app->get_real_path(
ao_app->get_evidence_path(p_evidence_image));
QPixmap f_pixmap(f_evidence_path);
pos_size_type icon_dimensions =

View File

@ -24,21 +24,16 @@ AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app, bool make_static) : Q
AOImage::~AOImage() {}
bool AOImage::set_image(QString p_path, QString p_misc)
bool AOImage::set_image(QString p_image, QString p_misc)
{
// Check if the user wants animated themes
if (!is_static && ao_app->get_animated_theme())
// We want an animated image
p_path = ao_app->get_image(p_path, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_misc);
else
// Grab a static variant of the image
p_path = ao_app->get_image_path(ao_app->get_asset_paths(p_path, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_misc), true);
p_image = ao_app->get_image(p_image, ao_app->current_theme, ao_app->get_subtheme(),
ao_app->default_theme, p_misc, "", "", is_static || !ao_app->get_animated_theme());
if (!file_exists(p_path)) {
qDebug() << "Warning: Image" << p_path << "not found! Can't set!";
if (!file_exists(p_image)) {
qDebug() << "Warning: Image" << p_image << "not found! Can't set!";
return false;
}
path = p_path;
path = p_image;
if (!is_static) {
movie->stop();
movie->setFileName(path);

View File

@ -12,16 +12,16 @@ AOLayer::AOLayer(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent)
shfx_timer = new QTimer(this);
shfx_timer->setTimerType(Qt::PreciseTimer);
shfx_timer->setSingleShot(true);
connect(shfx_timer, SIGNAL(timeout()), this, SLOT(shfx_timer_done()));
connect(shfx_timer, &QTimer::timeout, this, &AOLayer::shfx_timer_done);
ticker = new QTimer(this);
ticker->setTimerType(Qt::PreciseTimer);
ticker->setSingleShot(false);
connect(ticker, SIGNAL(timeout()), this, SLOT(movie_ticker()));
connect(ticker, &QTimer::timeout, this, &AOLayer::movie_ticker);
preanim_timer = new QTimer(this);
preanim_timer->setSingleShot(true);
connect(preanim_timer, SIGNAL(timeout()), this, SLOT(preanim_done()));
connect(preanim_timer, &QTimer::timeout, this, &AOLayer::preanim_done);
}
BackgroundLayer::BackgroundLayer(QWidget *p_parent, AOApplication *p_ao_app)
@ -52,7 +52,7 @@ StickerLayer::StickerLayer(QWidget *p_parent, AOApplication *p_ao_app)
QString AOLayer::find_image(QStringList p_list)
{
QString image_path;
for (QString path : p_list) {
for (const QString &path : p_list) {
#ifdef DEBUG_MOVIE
qDebug() << "checking path " << path;
#endif
@ -138,14 +138,15 @@ void BackgroundLayer::load_image(QString p_filename)
{
play_once = false;
cull_image = false;
QString design_path = ao_app->get_background_path("design.ini");
VPath design_path = ao_app->get_background_path("design.ini");
transform_mode =
ao_app->get_scaling(ao_app->read_design_ini("scaling", design_path));
stretch = ao_app->read_design_ini("stretch", design_path).startsWith("true");
#ifdef DEBUG_MOVIE
qDebug() << "[BackgroundLayer] BG loaded: " << p_filename;
#endif
start_playback(ao_app->get_image_suffix(ao_app->get_background_path(p_filename)));
QString final_path = ao_app->get_image_suffix(ao_app->get_background_path(p_filename));
start_playback(final_path);
play();
}
@ -179,15 +180,16 @@ void CharLayer::load_image(QString p_filename, QString p_charname,
last_emote = current_emote;
last_prefix = prefix;
is_preanim = p_is_preanim;
if ((p_filename.left(3) == "(a)") || (p_filename.left(3) == "(b)")) {
prefix = p_filename.left(3);
if ((p_filename.left(3) == "(a)") || (p_filename.left(3) == "(b)")) { // if we are playing an idle or talking animation
prefix = p_filename.left(3); // separate the prefix from the emote name
current_emote = p_filename.mid(3, -1);
}
else if ((duration > 0) || (p_filename.left(3) == "(c)")) {
if (p_filename.left(3) == "(c)") {
prefix = "(c)";
else if ((duration > 0) || (p_filename.left(3) == "(c)")) { // else if we are playing a preanim or postanim
if (p_filename.left(3) == "(c)") { // if we are playing a postanim
prefix = "(c)"; // separate the prefix from the emote name
current_emote = p_filename.mid(3, -1);
}
// pre/postanim specific flags
is_preanim = true;
play_once = true;
preanim_timer->start(duration);
@ -197,7 +199,7 @@ void CharLayer::load_image(QString p_filename, QString p_charname,
<< current_emote << " from character: " << p_charname
<< " continuous: " << continuous;
#endif
QStringList pathlist = {
QVector<VPath> pathlist { // cursed character path resolution vector
ao_app->get_character_path(
p_charname, prefix + current_emote), // Default path
ao_app->get_character_path(
@ -207,7 +209,7 @@ void CharLayer::load_image(QString p_filename, QString p_charname,
ao_app->get_character_path(
p_charname,
current_emote), // Just use the non-prefixed image, animated or not
current_emote, // The path by itself after the above fail
VPath(current_emote), // The path by itself after the above fail
ao_app->get_theme_path("placeholder"), // Theme placeholder path
ao_app->get_theme_path(
"placeholder", ao_app->default_theme)}; // Default theme placeholder path
@ -232,7 +234,7 @@ void EffectLayer::load_image(QString p_filename, bool p_looping)
play_once = true;
continuous = false;
force_continuous = true;
start_playback(p_filename); // handled in its own file before we see it
start_playback(p_filename); // path resolution is handled by the caller for EffectLayer objects
play();
}
@ -269,6 +271,13 @@ void CharLayer::start_playback(QString p_image)
void AOLayer::start_playback(QString p_image)
{
if (p_image == "") {// image wasn't found by the path resolution function
this->kill();
return;
}
QMutexLocker locker(&mutex);
if (frame_loader.isRunning())
exit_loop = true; // tell the loader to stop, we have a new image to load
this->show();
if (!ao_app->is_continuous_enabled()) {
@ -276,7 +285,7 @@ void AOLayer::start_playback(QString p_image)
force_continuous = true;
}
if ((last_path == p_image) && (!force_continuous))
if (((last_path == p_image) && (!force_continuous)) || p_image == "")
return;
#ifdef DEBUG_MOVIE
@ -296,55 +305,36 @@ void AOLayer::start_playback(QString p_image)
stretch = stretch_override.startsWith("true");
#ifdef DEBUG_MOVIE
qDebug() << "stretch:" << stretch << "filename:" << p_image;
qDebug() << "[AOLayer::start_playback] Stretch:" << stretch << "Filename:" << p_image;
#endif
m_reader.setFileName(p_image);
if (m_reader.loopCount() == 0)
play_once = true;
if (!continuous)
frame = 0;
last_max_frames = max_frames;
max_frames = m_reader.imageCount();
if (((continuous) && (max_frames != last_max_frames)) || max_frames == 0) {
if (!continuous
|| ((continuous) && (max_frames != last_max_frames))
|| max_frames == 0
|| frame >= max_frames) {
frame = 0;
continuous = false;
}
// CANTFIX: this causes a hitch
// The correct way of doing this would be to use QImageReader::jumpToImage()
// and populate missing data in the movie ticker when it's needed. This is
// unfortunately completely impossible, because QImageReader::jumpToImage() is
// not implemented in any image format AO2 is equipped to use. Instead, the
// default behavior is used - that is, absolutely nothing.
// This is why continuous playback can be toggled off.
if (continuous) {
for (int i = frame; i--;) {
if (i <= -1)
break;
QPixmap l_pixmap = this->get_pixmap(m_reader.read());
int l_delay = m_reader.nextImageDelay();
movie_frames.append(l_pixmap);
movie_delays.append(l_delay);
}
}
frame_loader = QtConcurrent::run(this, &AOLayer::populate_vectors);
last_path = p_image;
QPixmap f_pixmap = this->get_pixmap(m_reader.read());
int f_delay = m_reader.nextImageDelay();
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
this->set_frame(movie_frames[frame]);
this->set_frame(f_pixmap);
if (max_frames > 1) {
movie_frames.append(f_pixmap);
movie_delays.append(f_delay);
}
else if (max_frames <= 1) {
if (max_frames <= 1) {
duration = static_duration;
#ifdef DEBUG_MOVIE
qDebug() << "max_frames is <= 1, using static duration";
qDebug() << "[AOLayer::start_playback] max_frames is <= 1, using static duration";
#endif
}
if (duration > 0 && cull_image == true)
shfx_timer->start(duration);
#ifdef DEBUG_MOVIE
qDebug() << max_frames << "Setting image to " << image_path
qDebug() << "[AOLayer::start_playback] Max frames:" << max_frames << "Setting image to " << p_image
<< "Time taken to process image:" << actual_time.elapsed();
actual_time.restart();
@ -375,8 +365,12 @@ void AOLayer::play()
else
this->freeze();
}
else
else {
while (movie_delays.size() <= frame) {
frameAdded.wait(&mutex);
}
ticker->start(this->get_frame_delay(movie_delays[frame]));
}
}
void AOLayer::set_play_once(bool p_play_once) { play_once = p_play_once; }
@ -454,7 +448,7 @@ void CharLayer::load_network_effects()
// data, let's yank it in.
effect += f_data;
#ifdef DEBUG_MOVIE
qDebug() << effect << f_data << "frame" << f_frame << "for"
qDebug() << "[CharLayer::load_network_effects]" << effect << f_data << "frame" << f_frame << "for"
<< m_emote;
#endif
movie_effects[f_frame].append(effect);
@ -473,24 +467,24 @@ void CharLayer::play_frame_effect(int p_frame)
if (p_frame < max_frames) {
foreach (QString effect, movie_effects[p_frame]) {
if (effect == "shake") {
shake();
emit shake();
#ifdef DEBUG_MOVIE
qDebug() << "Attempting to play shake on frame" << frame;
qDebug() << "[CharLayer::play_frame_effect] Attempting to play shake on frame" << frame;
#endif
}
if (effect == "flash") {
flash();
emit flash();
#ifdef DEBUG_MOVIE
qDebug() << "Attempting to play flash on frame" << frame;
qDebug() << "[CharLayer::play_frame_effect] Attempting to play flash on frame" << frame;
#endif
}
if (effect.startsWith("sfx^")) {
QString sfx = effect.section("^", 1);
play_sfx(sfx);
emit play_sfx(sfx);
#ifdef DEBUG_MOVIE
qDebug() << "Attempting to play sfx" << sfx << "on frame" << frame;
qDebug() << "[CharLayer::play_frame_effect] Attempting to play sfx" << sfx << "on frame" << frame;
#endif
}
}
@ -544,21 +538,38 @@ void AOLayer::movie_ticker()
else
frame = 0;
}
// qint64 difference = elapsed - movie_delays[frame];
if (frame >= movie_frames.size()) {
movie_frames.append(this->get_pixmap(m_reader.read()));
movie_delays.append(m_reader.nextImageDelay());
mutex.lock();
while (frame >= movie_frames.size() && frame < max_frames) { // oops! our frame isn't ready yet
frameAdded.wait(&mutex); // wait for a new frame to be added, then check again
}
mutex.unlock();
#ifdef DEBUG_MOVIE
qDebug() << frame << movie_delays[frame]
<< "actual time taken from last frame:" << actual_time.restart();
qDebug() << "[AOLayer::movie_ticker] Frame:" << frame << "Delay:" << movie_delays[frame]
<< "Actual time taken from last frame:" << actual_time.restart();
#endif
this->set_frame(movie_frames[frame]);
ticker->setInterval(this->get_frame_delay(movie_delays[frame]));
}
void AOLayer::populate_vectors() {
while (movie_frames.size() < max_frames && !exit_loop) {
load_next_frame();
#ifdef DEBUG_MOVIE
qDebug() << "[AOLayer::populate_vectors] Loaded frame" << movie_frames.size();
#endif
}
exit_loop = false;
}
void AOLayer::load_next_frame() {
//QMutexLocker locker(&mutex);
mutex.lock();
movie_frames.append(this->get_pixmap(m_reader.read()));
movie_delays.append(m_reader.nextImageDelay());
mutex.unlock();
frameAdded.wakeAll();
}
void CharLayer::preanim_done()
{
if (is_preanim)
@ -571,7 +582,7 @@ void AOLayer::preanim_done()
{
ticker->stop();
preanim_timer->stop();
done();
emit done();
}
void AOLayer::shfx_timer_done()
@ -581,5 +592,5 @@ void AOLayer::shfx_timer_done()
qDebug() << "shfx timer signaled done";
#endif
// signal connected to courtroom object, let it figure out what to do
done();
emit done();
}

View File

@ -1,22 +0,0 @@
#include "aolineedit.h"
AOLineEdit::AOLineEdit(QWidget *parent) : QLineEdit(parent) {}
void AOLineEdit::mouseDoubleClickEvent(QMouseEvent *e)
{
QLineEdit::mouseDoubleClickEvent(e);
double_clicked();
}
void AOLineEdit::focusOutEvent(QFocusEvent *ev)
{
int start = selectionStart();
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
int len = selectionLength();
#else
int len = selectedText().length();
#endif
QLineEdit::focusOutEvent(ev);
if (p_selection && start != -1 && len != -1)
this->setSelection(start, len);
}

View File

@ -19,7 +19,7 @@ int AOMusicPlayer::play(QString p_song, int channel, bool loop,
channel = channel % m_channelmax;
if (channel < 0) // wtf?
return BASS_ERROR_NOCHAN;
QString f_path = ao_app->get_music_path(p_song);
QString f_path = ao_app->get_real_path(ao_app->get_music_path(p_song));
unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE |
BASS_UNICODE | BASS_ASYNCFILE;
@ -150,8 +150,8 @@ void AOMusicPlayer::set_volume(int p_value, int channel)
void CALLBACK loopProc(HSYNC handle, DWORD channel, DWORD data, void *user)
{
UNUSED(handle);
UNUSED(data);
Q_UNUSED(handle);
Q_UNUSED(data);
QWORD loop_start = *(static_cast<unsigned *>(user));
BASS_ChannelLock(channel, true);
BASS_ChannelSetPosition(channel, loop_start, BASS_POS_BYTE);

View File

@ -5,6 +5,8 @@
#include "bass.h"
#include "networkmanager.h"
#include <QFileDialog>
AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint)
{
@ -13,7 +15,7 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
// Setting up the basics.
setWindowFlag(Qt::WindowCloseButtonHint);
setWindowTitle(tr("Settings"));
resize(400, 408);
resize(450, 408);
ui_settings_buttons = new QDialogButtonBox(this);
@ -28,12 +30,12 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
QDialogButtonBox::Save |
QDialogButtonBox::RestoreDefaults);
QObject::connect(ui_settings_buttons, SIGNAL(accepted()), this,
SLOT(save_pressed()));
QObject::connect(ui_settings_buttons, SIGNAL(rejected()), this,
SLOT(discard_pressed()));
QObject::connect(ui_settings_buttons, SIGNAL(clicked(QAbstractButton*)), this,
SLOT(button_clicked(QAbstractButton*)));
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);
@ -74,16 +76,23 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_theme_combobox = new QComboBox(ui_form_layout_widget);
// Fill the combobox with the names of the themes.
QDirIterator it(ao_app->get_base_path() + "themes", QDir::Dirs,
QDirIterator::NoIteratorFlags);
while (it.hasNext()) {
QString actualname = QDir(it.next()).dirName();
if (actualname != "." && actualname != "..")
ui_theme_combobox->addItem(actualname);
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);
}
}
}
QObject::connect(ui_theme_combobox, SIGNAL(currentIndexChanged(int)), this,
SLOT(theme_changed(int)));
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;
@ -116,8 +125,8 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
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);
QObject::connect(ui_theme_reload_button, SIGNAL(clicked()), this,
SLOT(on_reload_theme_clicked()));
connect(ui_theme_reload_button, &QPushButton::clicked, this,
&AOOptionsDialog::on_reload_theme_clicked);
row += 1;
ui_animated_theme_lbl = new QLabel(ui_form_layout_widget);
@ -208,8 +217,33 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_log_timestamp_cb = new QCheckBox(ui_form_layout_widget);
connect(ui_log_timestamp_cb, &QCheckBox::stateChanged, this, &AOOptionsDialog::timestamp_cb_changed);
ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_log_timestamp_cb);
row += 1;
ui_log_timestamp_format_lbl = new QLabel(ui_form_layout_widget);
ui_log_timestamp_format_lbl->setText(tr("Log timestamp format:\n") + QDateTime::currentDateTime().toString(ao_app->get_log_timestamp_format()));
ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_log_timestamp_format_lbl);
ui_log_timestamp_format_combobox = new QComboBox(ui_form_layout_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_gameplay_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_layout_widget);
ui_log_ic_actions_lbl->setText(tr("Log IC actions:"));
@ -222,7 +256,6 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_log_ic_actions_cb);
row += 1;
ui_stay_time_lbl = new QLabel(ui_form_layout_widget);
ui_stay_time_lbl->setText(tr("Text Stay Time:"));
@ -903,7 +936,130 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app)
ui_casing_layout->setWidget(row, QFormLayout::FieldRole, ui_log_cb);
// privacy policy.
// 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 will be searched in the order provided."));
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 dir = QFileDialog::getExistingDirectory(this, tr("Select a base folder"),
QApplication::applicationDirPath(),
QFileDialog::ShowDirsOnly);
if (dir.isEmpty())
return;
QListWidgetItem *dir_item = new QListWidgetItem(dir);
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, [=] {
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, [=] {
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, [=] {
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, [=] {
asset_cache_dirty = true;
ui_mount_clear_cache->setEnabled(false);
});
connect(ui_mount_list, &QListWidget::itemSelectionChanged, 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);
});
// Privacy tab
ui_privacy_tab = new QWidget(this);
ui_settings_tabs->addTab(ui_privacy_tab, tr("Privacy"));
@ -965,6 +1121,7 @@ void AOOptionsDialog::update_values() {
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());
@ -1002,6 +1159,13 @@ void AOOptionsDialog::update_values() {
ui_blips_volume_spinbox->setValue(ao_app->get_default_blip());
ui_bliprate_spinbox->setValue(ao_app->read_blip_rate());
ui_default_showname_textbox->setText(ao_app->get_default_showname());
auto *defaultMount = new QListWidgetItem(tr("%1 (default)")
.arg(ao_app->get_base_path()));
defaultMount->setFlags(Qt::ItemFlag::NoItemFlags);
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) {
@ -1028,6 +1192,7 @@ void AOOptionsDialog::save_pressed()
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());
@ -1083,9 +1248,16 @@ void AOOptionsDialog::save_pressed()
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 (asset_cache_dirty)
ao_app->invalidate_lookup_cache();
if (audioChanged)
ao_app->initBASS();
@ -1147,6 +1319,10 @@ void AOOptionsDialog::theme_changed(int i) {
}
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__))

View File

@ -47,12 +47,6 @@ void AOSfxPlayer::play(QString p_sfx, QString p_character, QString p_misc)
set_volume_internal(m_volume);
BASS_ChannelSetDevice(m_stream_list[m_channel], BASS_GetDevice());
int f_bass_error = BASS_ErrorGetCode();
if (f_bass_error == BASS_ERROR_DEVICE) {
ao_app->doBASSreset();
BASS_ChannelSetDevice(m_stream_list[m_channel], BASS_GetDevice());
}
BASS_ChannelPlay(m_stream_list[m_channel], false);
BASS_ChannelSetSync(m_stream_list[m_channel], BASS_SYNC_DEV_FAIL, 0,
ao_app->BASSreset, 0);

View File

@ -1,17 +0,0 @@
#include "aotextedit.h"
AOTextEdit::AOTextEdit(QWidget *parent) : QPlainTextEdit(parent)
{
this->setReadOnly(true);
// connect(this, SIGNAL(returnPressed()), this, SLOT(on_enter_pressed()));
}
void AOTextEdit::mouseDoubleClickEvent(QMouseEvent *e)
{
QPlainTextEdit::mouseDoubleClickEvent(e);
this->setReadOnly(false);
}
void AOTextEdit::on_enter_pressed() { this->setReadOnly(true); }

View File

@ -52,25 +52,25 @@ void Courtroom::construct_char_select()
ui_char_taken->setText(tr("Taken"));
ui_char_taken->setObjectName("ui_char_taken");
connect(ui_char_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
this, SLOT(on_char_list_double_clicked(QTreeWidgetItem *, int)));
connect(ui_char_list, &QTreeWidget::itemDoubleClicked,
this, &Courtroom::on_char_list_double_clicked);
connect(ui_back_to_lobby, SIGNAL(clicked()), this,
SLOT(on_back_to_lobby_clicked()));
connect(ui_back_to_lobby, &AOButton::clicked, this,
&Courtroom::on_back_to_lobby_clicked);
connect(ui_char_select_left, SIGNAL(clicked()), this,
SLOT(on_char_select_left_clicked()));
connect(ui_char_select_right, SIGNAL(clicked()), this,
SLOT(on_char_select_right_clicked()));
connect(ui_char_select_left, &AOButton::clicked, this,
&Courtroom::on_char_select_left_clicked);
connect(ui_char_select_right, &AOButton::clicked, this,
&Courtroom::on_char_select_right_clicked);
connect(ui_spectator, SIGNAL(clicked()), this, SLOT(on_spectator_clicked()));
connect(ui_spectator, &AOButton::clicked, this, &Courtroom::on_spectator_clicked);
connect(ui_char_search, SIGNAL(textEdited(const QString &)), this,
SLOT(on_char_search_changed()));
connect(ui_char_passworded, SIGNAL(stateChanged(int)), this,
SLOT(on_char_passworded_clicked()));
connect(ui_char_taken, SIGNAL(stateChanged(int)), this,
SLOT(on_char_taken_clicked()));
connect(ui_char_search, &QLineEdit::textEdited,this,
&Courtroom::on_char_search_changed);
connect(ui_char_passworded, &QCheckBox::stateChanged, this,
&Courtroom::on_char_passworded_clicked);
connect(ui_char_taken, &QCheckBox::stateChanged, this,
&Courtroom::on_char_taken_clicked);
}
@ -116,7 +116,7 @@ void Courtroom::set_char_select_page()
ui_char_select_left->hide();
ui_char_select_right->hide();
for (AOCharButton *i_button : ui_char_button_list) {
for (AOCharButton *i_button : qAsConst(ui_char_button_list)) {
i_button->reset();
i_button->hide();
i_button->move(0, 0);
@ -147,7 +147,7 @@ void Courtroom::set_char_select_page()
void Courtroom::on_char_list_double_clicked(QTreeWidgetItem *p_item, int column)
{
UNUSED(column);
Q_UNUSED(column);
int cid = p_item->text(1).toInt();
if (cid == -1 && !p_item->isExpanded()) {
p_item->setExpanded(true);
@ -164,8 +164,8 @@ void Courtroom::char_clicked(int n_char)
{
if (n_char != -1)
{
QString char_ini_path =
ao_app->get_character_path(char_list.at(n_char).name, "char.ini");
QString char_ini_path = ao_app->get_real_path(
ao_app->get_character_path(char_list.at(n_char).name, "char.ini"));
qDebug() << "char_ini_path" << char_ini_path;
@ -298,9 +298,9 @@ void Courtroom::character_loading_finished()
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))
.arg(QString::number(ao_app->char_list_size)));
tr("Generating chars:\n%1/%2").arg(
QString::number(ao_app->generated_chars),
QString::number(ao_app->char_list_size)));
}
}
ui_char_list->expandAll();

View File

@ -7,7 +7,7 @@ chatlogpiece::chatlogpiece()
message = tr("UNKNOWN");
color = 0;
action = "";
datetime = QDateTime::currentDateTime().toUTC();
datetime = QDateTime::currentDateTimeUtc();
}
chatlogpiece::chatlogpiece(QString p_name, QString p_showname,
@ -18,7 +18,7 @@ chatlogpiece::chatlogpiece(QString p_name, QString p_showname,
message = p_message;
action = p_action;
color = p_color;
datetime = QDateTime::currentDateTime().toUTC();
datetime = QDateTime::currentDateTimeUtc();
}
chatlogpiece::chatlogpiece(QString p_name, QString p_showname,

View File

@ -109,6 +109,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
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();
ui_ms_chatlog = new AOTextArea(this);
ui_ms_chatlog->setReadOnly(true);
@ -150,7 +151,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
ui_music_name->setText(tr("None"));
ui_music_name->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_music_name->setObjectName("ui_music_name");
for (int i = 0; i < max_clocks; i++) {
ui_clock[i] = new AOClockLabel(this);
ui_clock[i]->setAttribute(Qt::WA_TransparentForMouseEvents);
@ -164,10 +165,12 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
ui_ic_chat_name->setText(p_ao_app->get_default_showname());
ui_ic_chat_name->setObjectName("ui_ic_chat_name");
ui_ic_chat_message = new AOLineEdit(this);
ui_ic_chat_message = new QLineEdit(this);
ui_ic_chat_message->setFrame(false);
ui_ic_chat_message->setPlaceholderText(tr("Message"));
ui_ic_chat_message->preserve_selection(true);
ui_ic_chat_message_filter = new AOLineEditFilter();
ui_ic_chat_message_filter->preserve_selection = true;
ui_ic_chat_message->installEventFilter(ui_ic_chat_message_filter);
ui_ic_chat_message->setObjectName("ui_ic_chat_message");
ui_vp_sticker = new StickerLayer(ui_viewport, ao_app);
@ -396,154 +399,154 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
construct_char_select();
connect(keepalive_timer, SIGNAL(timeout()), this, SLOT(ping_server()));
connect(keepalive_timer, &QTimer::timeout, this, &Courtroom::ping_server);
connect(ui_vp_objection, SIGNAL(done()), this, SLOT(objection_done()));
connect(ui_vp_effect, SIGNAL(done()), this, SLOT(effect_done()));
connect(ui_vp_wtce, SIGNAL(done()), this, SLOT(effect_done()));
connect(ui_vp_player_char, SIGNAL(done()), this, SLOT(preanim_done()));
connect(ui_vp_player_char, SIGNAL(shake()), this, SLOT(do_screenshake()));
connect(ui_vp_player_char, SIGNAL(flash()), this, SLOT(do_flash()));
connect(ui_vp_player_char, SIGNAL(play_sfx(QString)), this,
SLOT(play_char_sfx(QString)));
connect(ui_vp_objection, &SplashLayer::done, this, &Courtroom::objection_done);
connect(ui_vp_effect, &EffectLayer::done, this, &Courtroom::effect_done);
connect(ui_vp_wtce, &SplashLayer::done, this, &Courtroom::effect_done);
connect(ui_vp_player_char, &CharLayer::done, this, &Courtroom::preanim_done);
connect(ui_vp_player_char, &CharLayer::shake, this, &Courtroom::do_screenshake);
connect(ui_vp_player_char, &CharLayer::flash, this, &Courtroom::do_flash);
connect(ui_vp_player_char, &CharLayer::play_sfx, this,
&Courtroom::play_char_sfx);
connect(text_delay_timer, SIGNAL(timeout()), this,
SLOT(start_chat_ticking()));
connect(text_delay_timer, &QTimer::timeout, this,
&Courtroom::start_chat_ticking);
connect(text_queue_timer, SIGNAL(timeout()), this,
SLOT(chatmessage_dequeue()));
connect(text_queue_timer, &QTimer::timeout, this,
&Courtroom::chatmessage_dequeue);
connect(sfx_delay_timer, SIGNAL(timeout()), this, SLOT(play_sfx()));
connect(sfx_delay_timer, &QTimer::timeout, this, &Courtroom::play_sfx);
connect(chat_tick_timer, SIGNAL(timeout()), this, SLOT(chat_tick()));
connect(chat_tick_timer, &QTimer::timeout, this, &Courtroom::chat_tick);
connect(ui_pos_dropdown, SIGNAL(currentIndexChanged(int)), this,
SLOT(on_pos_dropdown_changed(int)));
connect(ui_pos_dropdown, SIGNAL(editTextChanged(QString)), this,
SLOT(on_pos_dropdown_changed(QString)));
connect(ui_pos_remove, SIGNAL(clicked()), this, SLOT(on_pos_remove_clicked()));
connect(ui_pos_dropdown, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
QOverload<int>::of(&Courtroom::on_pos_dropdown_changed));
connect(ui_pos_dropdown, &QComboBox::editTextChanged, this,
QOverload<QString>::of(&Courtroom::on_pos_dropdown_changed));
connect(ui_pos_remove, &AOButton::clicked, this, &Courtroom::on_pos_remove_clicked);
connect(ui_iniswap_dropdown, SIGNAL(currentIndexChanged(int)), this,
SLOT(on_iniswap_dropdown_changed(int)));
connect(ui_iniswap_dropdown, SIGNAL(customContextMenuRequested(QPoint)), this,
SLOT(on_iniswap_context_menu_requested(QPoint)));
connect(ui_iniswap_remove, SIGNAL(clicked()), this,
SLOT(on_iniswap_remove_clicked()));
connect(ui_iniswap_dropdown, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&Courtroom::on_iniswap_dropdown_changed);
connect(ui_iniswap_dropdown, &QComboBox::customContextMenuRequested, this,
&Courtroom::on_iniswap_context_menu_requested);
connect(ui_iniswap_remove, &AOButton::clicked, this,
&Courtroom::on_iniswap_remove_clicked);
connect(ui_sfx_dropdown, SIGNAL(currentIndexChanged(int)), this,
SLOT(on_sfx_dropdown_changed(int)));
connect(ui_sfx_dropdown, SIGNAL(editTextChanged(QString)), this,
SLOT(on_sfx_dropdown_custom(QString)));
connect(ui_sfx_dropdown, SIGNAL(customContextMenuRequested(QPoint)), this,
SLOT(on_sfx_context_menu_requested(QPoint)));
connect(ui_sfx_remove, SIGNAL(clicked()), this,
SLOT(on_sfx_remove_clicked()));
connect(ui_sfx_dropdown, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&Courtroom::on_sfx_dropdown_changed);
connect(ui_sfx_dropdown, &QComboBox::editTextChanged, this,
&Courtroom::on_sfx_dropdown_custom);
connect(ui_sfx_dropdown, &QComboBox::customContextMenuRequested, this,
&Courtroom::on_sfx_context_menu_requested);
connect(ui_sfx_remove, &AOButton::clicked, this,
&Courtroom::on_sfx_remove_clicked);
connect(ui_effects_dropdown, SIGNAL(currentIndexChanged(int)), this,
SLOT(on_effects_dropdown_changed(int)));
connect(ui_effects_dropdown, SIGNAL(customContextMenuRequested(QPoint)), this,
SLOT(on_effects_context_menu_requested(QPoint)));
connect(ui_effects_dropdown, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&Courtroom::on_effects_dropdown_changed);
connect(ui_effects_dropdown, &QComboBox::customContextMenuRequested, this,
&Courtroom::on_effects_context_menu_requested);
connect(ui_music_search, SIGNAL(returnPressed()), this,
SLOT(on_music_search_return_pressed()));
connect(ui_mute_list, SIGNAL(clicked(QModelIndex)), this,
SLOT(on_mute_list_clicked(QModelIndex)));
connect(ui_music_search, &QLineEdit::returnPressed, this,
&Courtroom::on_music_search_return_pressed);
connect(ui_mute_list, &QListWidget::clicked, this,
&Courtroom::on_mute_list_clicked);
connect(ui_ic_chat_message, SIGNAL(returnPressed()), this,
SLOT(on_chat_return_pressed()));
connect(ui_ic_chat_message, &QLineEdit::returnPressed, this,
&Courtroom::on_chat_return_pressed);
connect(ui_ooc_chat_message, SIGNAL(returnPressed()), this,
SLOT(on_ooc_return_pressed()));
connect(ui_ooc_chat_message, &QLineEdit::returnPressed, this,
&Courtroom::on_ooc_return_pressed);
connect(ui_music_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
this, SLOT(on_music_list_double_clicked(QTreeWidgetItem *, int)));
connect(ui_music_list, SIGNAL(customContextMenuRequested(QPoint)), this,
SLOT(on_music_list_context_menu_requested(QPoint)));
connect(ui_music_list, &QTreeWidget::itemDoubleClicked,
this, &Courtroom::on_music_list_double_clicked);
connect(ui_music_list, &QTreeWidget::customContextMenuRequested, this,
&Courtroom::on_music_list_context_menu_requested);
connect(ui_area_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this,
SLOT(on_area_list_double_clicked(QTreeWidgetItem *, int)));
connect(ui_area_list, &QTreeWidget::itemDoubleClicked, this,
&Courtroom::on_area_list_double_clicked);
connect(ui_hold_it, SIGNAL(clicked()), this, SLOT(on_hold_it_clicked()));
connect(ui_objection, SIGNAL(clicked()), this, SLOT(on_objection_clicked()));
connect(ui_take_that, SIGNAL(clicked()), this, SLOT(on_take_that_clicked()));
connect(ui_custom_objection, SIGNAL(clicked()), this,
SLOT(on_custom_objection_clicked()));
connect(ui_hold_it, &AOButton::clicked, this, &Courtroom::on_hold_it_clicked);
connect(ui_objection, &AOButton::clicked, this, &Courtroom::on_objection_clicked);
connect(ui_take_that, &AOButton::clicked, this, &Courtroom::on_take_that_clicked);
connect(ui_custom_objection, &AOButton::clicked, this,
&Courtroom::on_custom_objection_clicked);
connect(ui_custom_objection,
SIGNAL(customContextMenuRequested(const QPoint &)), this,
SLOT(show_custom_objection_menu(const QPoint &)));
&AOButton::customContextMenuRequested, this,
&Courtroom::show_custom_objection_menu);
connect(ui_realization, SIGNAL(clicked()), this,
SLOT(on_realization_clicked()));
connect(ui_screenshake, SIGNAL(clicked()), this,
SLOT(on_screenshake_clicked()));
connect(ui_realization, &AOButton::clicked, this,
&Courtroom::on_realization_clicked);
connect(ui_screenshake, &AOButton::clicked, this,
&Courtroom::on_screenshake_clicked);
connect(ui_mute, SIGNAL(clicked()), this, SLOT(on_mute_clicked()));
connect(ui_mute, &AOButton::clicked, this, &Courtroom::on_mute_clicked);
connect(ui_defense_minus, SIGNAL(clicked()), this,
SLOT(on_defense_minus_clicked()));
connect(ui_defense_plus, SIGNAL(clicked()), this,
SLOT(on_defense_plus_clicked()));
connect(ui_prosecution_minus, SIGNAL(clicked()), this,
SLOT(on_prosecution_minus_clicked()));
connect(ui_prosecution_plus, SIGNAL(clicked()), this,
SLOT(on_prosecution_plus_clicked()));
connect(ui_defense_minus, &AOButton::clicked, this,
&Courtroom::on_defense_minus_clicked);
connect(ui_defense_plus, &AOButton::clicked, this,
&Courtroom::on_defense_plus_clicked);
connect(ui_prosecution_minus, &AOButton::clicked, this,
&Courtroom::on_prosecution_minus_clicked);
connect(ui_prosecution_plus, &AOButton::clicked, this,
&Courtroom::on_prosecution_plus_clicked);
connect(ui_text_color, SIGNAL(currentIndexChanged(int)), this,
SLOT(on_text_color_changed(int)));
connect(ui_text_color, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&Courtroom::on_text_color_changed);
connect(ui_music_slider, SIGNAL(valueChanged(int)), this,
SLOT(on_music_slider_moved(int)));
connect(ui_sfx_slider, SIGNAL(valueChanged(int)), this,
SLOT(on_sfx_slider_moved(int)));
connect(ui_blip_slider, SIGNAL(valueChanged(int)), this,
SLOT(on_blip_slider_moved(int)));
connect(ui_music_slider, &QSlider::valueChanged, this,
&Courtroom::on_music_slider_moved);
connect(ui_sfx_slider, &QSlider::valueChanged, this,
&Courtroom::on_sfx_slider_moved);
connect(ui_blip_slider, &QSlider::valueChanged, this,
&Courtroom::on_blip_slider_moved);
connect(ui_ooc_toggle, SIGNAL(clicked()), this,
SLOT(on_ooc_toggle_clicked()));
connect(ui_ooc_toggle, &AOButton::clicked, this,
&Courtroom::on_ooc_toggle_clicked);
connect(ui_music_search, SIGNAL(textChanged(QString)), this,
SLOT(on_music_search_edited(QString)));
connect(ui_music_search, &QLineEdit::textChanged, this,
&Courtroom::on_music_search_edited);
connect(ui_witness_testimony, SIGNAL(clicked()), this,
SLOT(on_witness_testimony_clicked()));
connect(ui_cross_examination, SIGNAL(clicked()), this,
SLOT(on_cross_examination_clicked()));
connect(ui_guilty, SIGNAL(clicked()), this, SLOT(on_guilty_clicked()));
connect(ui_not_guilty, SIGNAL(clicked()), this,
SLOT(on_not_guilty_clicked()));
connect(ui_witness_testimony, &AOButton::clicked, this,
&Courtroom::on_witness_testimony_clicked);
connect(ui_cross_examination, &AOButton::clicked, this,
&Courtroom::on_cross_examination_clicked);
connect(ui_guilty, &AOButton::clicked, this, &Courtroom::on_guilty_clicked);
connect(ui_not_guilty, &AOButton::clicked, this,
&Courtroom::on_not_guilty_clicked);
connect(ui_change_character, SIGNAL(clicked()), this,
SLOT(on_change_character_clicked()));
connect(ui_reload_theme, SIGNAL(clicked()), this,
SLOT(on_reload_theme_clicked()));
connect(ui_call_mod, SIGNAL(clicked()), this, SLOT(on_call_mod_clicked()));
connect(ui_settings, SIGNAL(clicked()), this, SLOT(on_settings_clicked()));
connect(ui_announce_casing, SIGNAL(clicked()), this,
SLOT(on_announce_casing_clicked()));
connect(ui_switch_area_music, SIGNAL(clicked()), this,
SLOT(on_switch_area_music_clicked()));
connect(ui_change_character, &AOButton::clicked, this,
&Courtroom::on_change_character_clicked);
connect(ui_reload_theme, &AOButton::clicked, this,
&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);
connect(ui_pre, SIGNAL(clicked()), this, SLOT(on_pre_clicked()));
connect(ui_flip, SIGNAL(clicked()), this, SLOT(on_flip_clicked()));
connect(ui_additive, SIGNAL(clicked()), this, SLOT(on_additive_clicked()));
connect(ui_guard, SIGNAL(clicked()), this, SLOT(on_guard_clicked()));
connect(ui_casing, SIGNAL(clicked()), this, SLOT(on_casing_clicked()));
connect(ui_pre, &AOButton::clicked, this, &Courtroom::on_pre_clicked);
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, SIGNAL(clicked()), this,
SLOT(on_showname_enable_clicked()));
connect(ui_showname_enable, &AOButton::clicked, this,
&Courtroom::on_showname_enable_clicked);
connect(ui_pair_button, SIGNAL(clicked()), this, SLOT(on_pair_clicked()));
connect(ui_pair_list, SIGNAL(clicked(QModelIndex)), this,
SLOT(on_pair_list_clicked(QModelIndex)));
connect(ui_pair_offset_spinbox, SIGNAL(valueChanged(int)), this,
SLOT(on_pair_offset_changed(int)));
connect(ui_pair_vert_offset_spinbox, SIGNAL(valueChanged(int)), this,
SLOT(on_pair_vert_offset_changed(int)));
connect(ui_pair_order_dropdown, SIGNAL(currentIndexChanged(int)), this,
SLOT(on_pair_order_dropdown_changed(int)));
connect(ui_pair_button, &AOButton::clicked, this, &Courtroom::on_pair_clicked);
connect(ui_pair_list, &QListWidget::clicked, this,
&Courtroom::on_pair_list_clicked);
connect(ui_pair_offset_spinbox, QOverload<int>::of(&QSpinBox::valueChanged), this,
&Courtroom::on_pair_offset_changed);
connect(ui_pair_vert_offset_spinbox, QOverload<int>::of(&QSpinBox::valueChanged), this,
&Courtroom::on_pair_vert_offset_changed);
connect(ui_pair_order_dropdown, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&Courtroom::on_pair_order_dropdown_changed);
connect(ui_evidence_button, SIGNAL(clicked()), this,
SLOT(on_evidence_button_clicked()));
connect(ui_evidence_button, &AOButton::clicked, this,
&Courtroom::on_evidence_button_clicked);
set_widgets();
@ -583,12 +586,12 @@ void Courtroom::set_mute_list()
QStringList sorted_mute_list;
for (char_type i_char : char_list)
for (const char_type &i_char : qAsConst(char_list))
sorted_mute_list.append(i_char.name);
sorted_mute_list.sort();
for (QString i_name : sorted_mute_list) {
for (const QString &i_name : sorted_mute_list) {
// mute_map.insert(i_name, false);
ui_mute_list->addItem(i_name);
}
@ -598,12 +601,12 @@ void Courtroom::set_pair_list()
{
QStringList sorted_pair_list;
for (char_type i_char : char_list)
for (const char_type &i_char : qAsConst(char_list))
sorted_pair_list.append(i_char.name);
sorted_pair_list.sort();
for (QString i_name : sorted_pair_list) {
for (const QString &i_name : sorted_pair_list) {
ui_pair_list->addItem(i_name);
}
}
@ -612,7 +615,7 @@ 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_theme_path(filename, ao_app->current_theme), QSettings::IniFormat);
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();
@ -706,12 +709,14 @@ void Courtroom::set_widgets()
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 != 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();
if (regenerate)
regenerate_ic_chatlog();
@ -767,7 +772,7 @@ void Courtroom::set_widgets()
ui_music_list->resetIndentation();
else
ui_music_list->setIndentation(music_list_indentation.toInt());
QString music_list_animated = ao_app->get_design_element("music_list_animated", "courtroom_design.ini");
if (music_list_animated == "1")
ui_music_list->setAnimated(true);
@ -1222,6 +1227,12 @@ void Courtroom::set_stylesheet(QWidget *widget)
void Courtroom::set_stylesheets()
{
set_stylesheet(this);
this->setStyleSheet(
"QFrame { background-color:transparent; } "
"QAbstractItemView { background-color: transparent; color: black; } "
"QLineEdit { background-color:transparent; }"
+ this->styleSheet()
);
}
void Courtroom::set_window_title(QString p_title)
@ -1326,7 +1337,7 @@ void Courtroom::set_background(QString p_background, bool display)
// Populate the dropdown list with all pos that exist on this bg
QStringList pos_list = {};
for (QString key : default_pos.keys()) {
for (const QString &key : default_pos) {
if (file_exists(ao_app->get_image_suffix(
ao_app->get_background_path(default_pos[key]))) || // if we have 2.8-style positions, e.g. def.png, wit.webp, hld.apng
file_exists(
@ -1334,7 +1345,7 @@ void Courtroom::set_background(QString p_background, bool display)
pos_list.append(default_pos[key]);
}
}
for (QString pos : ao_app->read_design_ini("positions", ao_app->get_background_path("design.ini")).split(",")) {
for (const QString &pos : ao_app->read_design_ini("positions", ao_app->get_background_path("design.ini")).split(",")) {
if (file_exists(ao_app->get_image_suffix(ao_app->get_background_path(pos)))) {
pos_list.append(pos);
}
@ -1492,11 +1503,11 @@ void Courtroom::update_character(int p_cid)
custom_obj_menu->setDefaultAction(action);
objection_custom = "";
}
if (dir_exists(
ao_app->get_character_path(current_char, "custom_objections"))) {
ui_custom_objection->show();
QDir directory(
QString custom_objection_dir = ao_app->get_real_path(
ao_app->get_character_path(current_char, "custom_objections"));
if (dir_exists(custom_objection_dir)) {
ui_custom_objection->show();
QDir directory(custom_objection_dir);
QStringList custom_obj = directory.entryList(QStringList() << "*.png"
<< "*.gif"
<< "*.apng"
@ -1631,7 +1642,7 @@ void Courtroom::list_music()
treeItem->setText(0, i_song_listname);
treeItem->setText(1, i_song);
QString song_path = ao_app->get_music_path(i_song);
QString song_path = ao_app->get_real_path(ao_app->get_music_path(i_song));
if (file_exists(song_path))
treeItem->setBackground(0, found_brush);
@ -1661,7 +1672,7 @@ void Courtroom::list_areas()
int n_listed_areas = 0;
for (int n_area = 0; n_area < area_list.size(); ++n_area) {
QString i_area = "";
QString i_area = "";
i_area.append(area_list.at(n_area));
if (ao_app->arup_enabled) {
@ -1751,7 +1762,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_auto_logging_enabled() && !ao_app->log_filename.isEmpty()) {
QString full = "[OOC][" + QDateTime::currentDateTime().toUTC().toString() + "] " + p_name + ": " + p_message;
QString full = "[OOC][" + QDateTime::currentDateTimeUtc().toString() + "] " + p_name + ": " + p_message;
ao_app->append_to_file(full, ao_app->log_filename, true);
}
}
@ -2190,7 +2201,7 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show
objection_mod = f_objection_mod.toInt();
}
QString f_custom_theme = ao_app->get_chat(f_char);
//QString f_custom_theme = ao_app->get_chat(f_char);
if (objection_mod <= 4 && objection_mod >= 1) {
QString shout_message;
switch (objection_mod) {
@ -2257,7 +2268,7 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show
if ((f_log_mode != IO_ONLY) && // if we're not in I/O only mode,
f_message.isEmpty() && // our current message is a blankpost,
!ic_chatlog_history.isEmpty() && // the chat log isn't empty,
last_ic_message == f_displayname + ":" && // the chat log's last message is a blank post, and
last_ic_message == f_displayname + ":" && // the chat log's last message is a blank post, and
last_ic_message.mid(0, last_ic_message.lastIndexOf(":")) == f_displayname) // the blankpost's showname is the same as ours
return; // Skip adding message
switch (f_log_mode) {
@ -2325,7 +2336,7 @@ bool Courtroom::handle_objection()
"custom", m_chatmessage[CHAR_NAME],
ao_app->get_chat(m_chatmessage[CHAR_NAME]));
}
break;
break;
m_chatmessage[EMOTE_MOD] = 1;
}
ui_vp_objection->load_image(
@ -2440,6 +2451,7 @@ void Courtroom::display_pair_character(QString other_charid, QString other_offse
// Play the other pair character's idle animation
QString filename = "(a)" + m_chatmessage[OTHER_EMOTE];
ui_vp_sideplayer_char->set_play_once(false);
ui_vp_sideplayer_char->load_image(filename, m_chatmessage[OTHER_NAME],
0, false);
}
@ -2751,7 +2763,7 @@ void Courtroom::handle_callwords()
// Obtain the current call words (Really? It does File I/O on every single message???)
QStringList call_words = ao_app->get_call_words();
// Loop through each word in the call words list
for (QString word : call_words) {
for (const QString &word : qAsConst(call_words)) {
// If our message contains that specific call word
if (f_message.contains(word, Qt::CaseInsensitive)) {
// Play the call word sfx on the modcall_player sound container
@ -2771,7 +2783,7 @@ void Courtroom::display_evidence_image()
if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
// shifted by 1 because 0 is no evidence per legacy standards
QString f_image = local_evidence_list.at(f_evi_id - 1).image;
QString f_evi_name = local_evidence_list.at(f_evi_id - 1).name;
//QString f_evi_name = local_evidence_list.at(f_evi_id - 1).name;
// def jud and hlp should display the evidence icon on the RIGHT side
bool is_left_side = !(side == "def" || side == "hlp" ||
side == "jud" || side == "jur");
@ -3119,7 +3131,7 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action,
if (log_timestamp) {
if (timestamp.isValid()) {
ui_ic_chatlog->textCursor().insertText(
"[" + timestamp.toString("h:mm:ss AP") + "] ", normal);
"[" + timestamp.toString(log_timestamp_format) + "] ", normal);
} else {
qDebug() << "could not insert invalid timestamp";
}
@ -3275,7 +3287,7 @@ void Courtroom::play_preanim(bool immediate)
void Courtroom::preanim_done()
{
// Currently, someone's talking over us mid-preanim...
if (anim_state != 1 && anim_state != 4)
if (anim_state != 1 && anim_state != 4 && anim_state != 5)
return;
anim_state = 1;
switch(m_chatmessage[DESK_MOD].toInt()) {
@ -3435,7 +3447,7 @@ void Courtroom::chat_tick()
}
ui_vp_chat_arrow->transform_mode = ao_app->get_misc_scaling(f_custom_theme);
ui_vp_chat_arrow->load_image("chat_arrow", f_custom_theme); // Chat stopped being processed, indicate that.
QString f_message_filtered = filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
QString f_message_filtered = filter_ic_text(f_message, true, -1, m_chatmessage[TEXT_COLOR].toInt());
for (int c = 0; c < max_colors; ++c) {
additive_previous = additive_previous.replace("$c" + QString::number(c), char_color_rgb_list.at(c).name(QColor::HexRgb));
f_message_filtered = f_message_filtered.replace("$c" + QString::number(c), char_color_rgb_list.at(c).name(QColor::HexRgb));
@ -3740,7 +3752,7 @@ void Courtroom::set_self_offset(QString p_list) {
int self_offset_v;
if (self_offsets.length() <= 1)
self_offset_v = 0;
else
else
self_offset_v = self_offsets[1].toInt();
ui_vp_player_char->move(ui_viewport->width() * self_offset / 100, ui_viewport->height() * self_offset_v / 100);
}
@ -3875,7 +3887,7 @@ void Courtroom::handle_song(QStringList *p_contents)
void Courtroom::handle_wtce(QString p_wtce, int variant)
{
QString sfx_file = "courtroom_sounds.ini";
//QString sfx_file = "courtroom_sounds.ini";
QString bg_misc = ao_app->read_design_ini("misc", ao_app->get_background_path("design.ini"));
QString sfx_name;
QString filename;
@ -3987,7 +3999,9 @@ void Courtroom::on_ooc_return_pressed()
{
QString ooc_message = ui_ooc_chat_message->text();
if (ooc_message.startsWith("/pos")) {
//We ignore it when the server is compatible with 2.8
//Using an arbitrary 2.8 feature flag certainly won't cause issues someday.
if (ooc_message.startsWith("/pos") & !ao_app->effects_enabled) {
if (ooc_message == "/pos jud") {
toggle_judge_buttons(true);
}
@ -3995,149 +4009,13 @@ void Courtroom::on_ooc_return_pressed()
toggle_judge_buttons(false);
}
}
else if (ooc_message.startsWith("/settings")) {
ui_ooc_chat_message->clear();
ao_app->call_settings_menu();
append_server_chatmessage("CLIENT", tr("You opened the settings menu."),
"1");
return;
}
else if (ooc_message.startsWith("/pair")) {
ui_ooc_chat_message->clear();
ooc_message.remove(0, 6);
bool ok;
int whom = ooc_message.toInt(&ok);
if (ok) {
if (whom > -1) {
other_charid = whom;
QString msg = tr("You will now pair up with %1 if they also choose "
"your character in return.")
.arg(char_list.at(whom).name);
append_server_chatmessage("CLIENT", msg, "1");
}
else {
other_charid = -1;
append_server_chatmessage(
"CLIENT", tr("You are no longer paired with anyone."), "1");
}
}
else {
append_server_chatmessage("CLIENT",
tr("Are you sure you typed that well? The char "
"ID could not be recognised."),
"1");
}
return;
}
else if (ooc_message.startsWith("/offset")) {
ui_ooc_chat_message->clear();
ooc_message.remove(0, 8);
bool ok;
int off = ooc_message.toInt(&ok);
if (ok) {
if (off >= -100 && off <= 100) {
char_offset = off;
QString msg =
tr("You have set your offset to %1%%.").arg(QString::number(off));
append_server_chatmessage("CLIENT", msg, "1");
}
else {
append_server_chatmessage(
"CLIENT", tr("Your offset must be between -100% and 100%!"), "1");
}
}
else {
append_server_chatmessage("CLIENT",
tr("That offset does not look like one."), "1");
}
return;
}
else if (ooc_message.startsWith("/voffset")) {
ui_ooc_chat_message->clear();
ooc_message.remove(0, 8);
bool ok;
int off = ooc_message.toInt(&ok);
if (ok) {
if (off >= -100 && off <= 100) {
char_vert_offset = off;
QString msg = tr("You have set your vertical offset to %1%%.")
.arg(QString::number(off));
append_server_chatmessage("CLIENT", msg, "1");
}
else {
append_server_chatmessage(
"CLIENT",
tr("Your vertical offset must be between -100% and 100%!"), "1");
}
}
else {
append_server_chatmessage(
"CLIENT", tr("That vertical offset does not look like one."), "1");
}
return;
}
else if (ooc_message.startsWith("/switch_am")) {
append_server_chatmessage(
"CLIENT", tr("You switched your music and area list."), "1");
on_switch_area_music_clicked();
ui_ooc_chat_message->clear();
return;
}
else if (ooc_message.startsWith("/enable_blocks")) {
append_server_chatmessage("CLIENT",
tr("You have forcefully enabled features that "
"the server may not support. You may not be "
"able to talk IC, or worse, because of this."),
"1");
ao_app->cccc_ic_support_enabled = true;
ao_app->arup_enabled = true;
ao_app->modcall_reason_enabled = true;
on_reload_theme_clicked();
ui_ooc_chat_message->clear();
return;
}
else if (ooc_message.startsWith("/non_int_pre")) {
if (ui_immediate->isChecked())
append_server_chatmessage(
"CLIENT", tr("Your pre-animations interrupt again."), "1");
else
append_server_chatmessage(
"CLIENT", tr("Your pre-animations will not interrupt text."), "1");
ui_immediate->setChecked(!ui_immediate->isChecked());
ui_ooc_chat_message->clear();
return;
}
else if (ooc_message.startsWith("/save_chatlog")) {
QFile file("chatlog.txt");
if (!file.open(QIODevice::WriteOnly | QIODevice::Text |
QIODevice::Truncate)) {
append_server_chatmessage(
"CLIENT", tr("Couldn't open chatlog.txt to write into."), "1");
ui_ooc_chat_message->clear();
return;
}
QTextStream out(&file);
out.setCodec("UTF-8");
foreach (chatlogpiece item, ic_chatlog_history) {
out << item.get_full() << '\n';
}
file.close();
append_server_chatmessage("CLIENT", tr("The IC chatlog has been saved."),
"1");
ui_ooc_chat_message->clear();
return;
}
else if (ooc_message.startsWith("/load_case")) {
if (ooc_message.startsWith("/load_case")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QStringList command = ooc_message.split(" ", QString::SkipEmptyParts);
#else
QStringList command = ooc_message.split(" ", Qt::SkipEmptyParts);
#endif
QDir casefolder("base/cases");
if (!casefolder.exists()) {
QDir::current().mkdir("base/" + casefolder.dirName());
@ -4234,8 +4112,11 @@ void Courtroom::on_ooc_return_pressed()
return;
}
else if (ooc_message.startsWith("/save_case")) {
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QStringList command = ooc_message.split(" ", QString::SkipEmptyParts);
#else
QStringList command = ooc_message.split(" ", Qt::SkipEmptyParts);
#endif
QDir casefolder("base/cases");
if (!casefolder.exists()) {
QDir::current().mkdir("base/" + casefolder.dirName());
@ -4429,8 +4310,9 @@ void Courtroom::set_iniswap_dropdown()
ui_iniswap_remove->hide();
return;
}
QStringList iniswaps = ao_app->get_list_file(
ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini")) + ao_app->get_list_file(ao_app->get_base_path() + "iniswaps.ini");
QStringList iniswaps =
ao_app->get_list_file(ao_app->get_character_path(char_list.at(m_cid).name, "iniswaps.ini")) +
ao_app->get_list_file(ao_app->get_base_path() + "iniswaps.ini");
iniswaps.removeDuplicates();
iniswaps.prepend(char_list.at(m_cid).name);
if (iniswaps.size() <= 0) {
@ -4486,7 +4368,8 @@ void Courtroom::on_iniswap_context_menu_requested(const QPoint &pos)
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addSeparator();
if (file_exists(ao_app->get_character_path(current_char, "char.ini")))
if (file_exists(ao_app->get_real_path(
ao_app->get_character_path(current_char, "char.ini"))))
menu->addAction(QString("Edit " + current_char + "/char.ini"), this,
SLOT(on_iniswap_edit_requested()));
if (ui_iniswap_dropdown->itemText(ui_iniswap_dropdown->currentIndex()) !=
@ -4497,7 +4380,7 @@ void Courtroom::on_iniswap_context_menu_requested(const QPoint &pos)
}
void Courtroom::on_iniswap_edit_requested()
{
QString p_path = ao_app->get_character_path(current_char, "char.ini");
QString p_path = ao_app->get_real_path(ao_app->get_character_path(current_char, "char.ini"));
if (!file_exists(p_path))
return;
QDesktopServices::openUrl(QUrl::fromLocalFile(p_path));
@ -4536,7 +4419,7 @@ void Courtroom::set_sfx_dropdown()
ao_app->get_base_path() + "soundlist.ini");
QStringList display_sounds;
for (QString sound : sound_list) {
for (const QString &sound : qAsConst(sound_list)) {
QStringList unpacked = sound.split("=");
QString display = unpacked[0].trimmed();
if (unpacked.size() > 1)
@ -4556,7 +4439,7 @@ void Courtroom::set_sfx_dropdown()
void Courtroom::on_sfx_dropdown_changed(int p_index)
{
UNUSED(p_index);
Q_UNUSED(p_index);
ui_ic_chat_message->setFocus();
ui_sfx_remove->hide();
custom_sfx = "";
@ -4574,7 +4457,8 @@ void Courtroom::on_sfx_context_menu_requested(const QPoint &pos)
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addSeparator();
if (file_exists(ao_app->get_character_path(current_char, "soundlist.ini")))
if (file_exists(ao_app->get_real_path(
ao_app->get_character_path(current_char, "soundlist.ini"))))
menu->addAction(QString("Edit " + current_char + "/soundlist.ini"), this,
SLOT(on_sfx_edit_requested()));
else
@ -4587,10 +4471,10 @@ void Courtroom::on_sfx_context_menu_requested(const QPoint &pos)
void Courtroom::on_sfx_edit_requested()
{
QString p_path = ao_app->get_character_path(current_char, "soundlist.ini");
QString p_path = ao_app->get_real_path(ao_app->get_character_path(current_char, "soundlist.ini"));
if (!file_exists(p_path)) {
p_path = ao_app->get_base_path() + "soundlist.ini";
}
}
QDesktopServices::openUrl(QUrl::fromLocalFile(p_path));
}
@ -4623,12 +4507,11 @@ void Courtroom::set_effects_dropdown()
// ICON-MAKING HELL
QString p_effect = ao_app->read_char_ini(current_char, "effects", "Options");
QString custom_path =
ao_app->get_base_path() + "misc/" + p_effect + "/icons/";
QString theme_path = ao_app->get_theme_path("effects/icons/");
QString default_path = ao_app->get_theme_path("effects/icons/", "default");
VPath custom_path("misc/" + p_effect + "/icons/");
VPath theme_path = ao_app->get_theme_path("effects/icons/");
VPath default_path = ao_app->get_theme_path("effects/icons/", "default");
for (int i = 0; i < ui_effects_dropdown->count(); ++i) {
QString entry = ui_effects_dropdown->itemText(i);
VPath entry = VPath(ui_effects_dropdown->itemText(i));
QString iconpath = ao_app->get_image_suffix(custom_path + entry);
if (!file_exists(iconpath)) {
iconpath = ao_app->get_image_suffix(theme_path + entry);
@ -4662,9 +4545,9 @@ void Courtroom::on_effects_context_menu_requested(const QPoint &pos)
}
void Courtroom::on_effects_edit_requested()
{
QString p_path = ao_app->get_theme_path("effects/");
QString p_path = ao_app->get_real_path(ao_app->get_theme_path("effects/"));
if (!dir_exists(p_path)) {
p_path = ao_app->get_theme_path("effects/", "default");
p_path = ao_app->get_real_path(ao_app->get_theme_path("effects/", "default"));
if (!dir_exists(p_path)) {
return;
}
@ -4674,7 +4557,7 @@ void Courtroom::on_effects_edit_requested()
void Courtroom::on_character_effects_edit_requested()
{
QString p_effect = ao_app->read_char_ini(current_char, "effects", "Options");
QString p_path = ao_app->get_base_path() + "misc/" + p_effect + "/";
QString p_path = ao_app->get_real_path(VPath("misc/" + p_effect + "/"));
if (!dir_exists(p_path))
return;
@ -4781,7 +4664,7 @@ void Courtroom::on_pair_list_clicked(QModelIndex p_index)
// Redo the character list.
QStringList sorted_pair_list;
for (char_type i_char : char_list)
for (const char_type &i_char : qAsConst(char_list))
sorted_pair_list.append(i_char.name);
sorted_pair_list.sort();
@ -4818,32 +4701,32 @@ void Courtroom::on_music_list_context_menu_requested(const QPoint &pos)
{
QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
menu->addAction(QString(tr("Stop Current Song")), this, SLOT(music_stop()));
menu->addAction(QString(tr("Play Random Song")), this, SLOT(music_random()));
menu->addAction(QString(tr("Stop Current Song")), this, &Courtroom::music_stop);
menu->addAction(QString(tr("Play Random Song")), this, &Courtroom::music_random);
menu->addSeparator();
menu->addAction(QString(tr("Expand All Categories")), this,
SLOT(music_list_expand_all()));
&Courtroom::music_list_expand_all);
menu->addAction(QString(tr("Collapse All Categories")), this,
SLOT(music_list_collapse_all()));
&Courtroom::music_list_collapse_all);
menu->addSeparator();
menu->addAction(new QAction(tr("Fade Out Previous"), this));
menu->actions().back()->setCheckable(true);
menu->actions().back()->setChecked(music_flags & FADE_OUT);
connect(menu->actions().back(), SIGNAL(toggled(bool)), this,
SLOT(music_fade_out(bool)));
connect(menu->actions().back(), &QAction::toggled, this,
&Courtroom::music_fade_out);
menu->addAction(new QAction(tr("Fade In"), this));
menu->actions().back()->setCheckable(true);
menu->actions().back()->setChecked(music_flags & FADE_IN);
connect(menu->actions().back(), SIGNAL(toggled(bool)), this,
SLOT(music_fade_in(bool)));
connect(menu->actions().back(), &QAction::toggled, this,
&Courtroom::music_fade_in);
menu->addAction(new QAction(tr("Synchronize"), this));
menu->actions().back()->setCheckable(true);
menu->actions().back()->setChecked(music_flags & SYNC_POS);
connect(menu->actions().back(), SIGNAL(toggled(bool)), this,
SLOT(music_synchronize(bool)));
connect(menu->actions().back(), &QAction::toggled, this,
&Courtroom::music_synchronize);
menu->popup(ui_music_list->mapToGlobal(pos));
}
@ -4908,7 +4791,7 @@ void Courtroom::music_stop(bool no_effects)
// If the fake song is not present in the music list
if (!music_list.contains(fake_song)) {
// Loop through our music list
for (QString song : music_list) {
for (const QString &song : qAsConst(music_list)) {
// Pick first song that does not contain a file extension
if (!song.contains('.')) {
// Use it as a fake song as the server we're working with must recognize song categories
@ -4936,7 +4819,7 @@ void Courtroom::music_stop(bool no_effects)
void Courtroom::on_area_list_double_clicked(QTreeWidgetItem *p_item, int column)
{
column = 0; // The metadata
UNUSED(column); // so gcc shuts up
Q_UNUSED(column); // so gcc shuts up
QString p_area = p_item->text(0);
QStringList packet_contents;

View File

@ -1,4 +1,5 @@
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QMessageBox>
#include <QTimer>
#include <functional>

View File

@ -97,7 +97,7 @@ void DemoServer::recv_data()
QStringList packet_list =
in_data.split("%", QString::SplitBehavior(QString::SkipEmptyParts));
for (QString packet : packet_list) {
for (const QString &packet : packet_list) {
AOPacket ao_packet(packet);
handle_packet(ao_packet);
}
@ -297,7 +297,7 @@ void DemoServer::load_demo(QString filename)
QTextStream out(&demo_file);
out.setCodec("UTF-8");
out << p_demo_data.dequeue();
for (QString line : p_demo_data) {
for (const QString &line : qAsConst(p_demo_data)) {
out << "\n" << line;
}
demo_file.flush();

View File

@ -15,13 +15,13 @@ void Courtroom::initialize_emotes()
ui_emote_dropdown = new QComboBox(this);
ui_emote_dropdown->setObjectName("ui_emote_dropdown");
connect(ui_emote_left, SIGNAL(clicked()), this,
SLOT(on_emote_left_clicked()));
connect(ui_emote_right, SIGNAL(clicked()), this,
SLOT(on_emote_right_clicked()));
connect(ui_emote_left, &AOButton::clicked, this,
&Courtroom::on_emote_left_clicked);
connect(ui_emote_right, &AOButton::clicked, this,
&Courtroom::on_emote_right_clicked);
connect(ui_emote_dropdown, SIGNAL(activated(int)), this,
SLOT(on_emote_dropdown_changed(int)));
connect(ui_emote_dropdown, QOverload<int>::of(&QComboBox::activated), this,
&Courtroom::on_emote_dropdown_changed);
}
void Courtroom::refresh_emotes()
@ -74,8 +74,8 @@ void Courtroom::refresh_emotes()
f_emote->set_id(n);
connect(f_emote, SIGNAL(emote_clicked(int)), this,
SLOT(on_emote_clicked(int)));
connect(f_emote, &AOEmoteButton::emote_clicked, this,
&Courtroom::on_emote_clicked);
++x_mod_count;
@ -96,7 +96,7 @@ void Courtroom::set_emote_page()
ui_emote_left->hide();
ui_emote_right->hide();
for (AOEmoteButton *i_button : ui_emote_list) {
for (AOEmoteButton *i_button : qAsConst(ui_emote_list)) {
i_button->hide();
}

View File

@ -6,7 +6,9 @@ void Courtroom::initialize_evidence()
ui_evidence->setObjectName("ui_evidence");
// ui_evidence_name = new QLabel(ui_evidence);
ui_evidence_name = new AOLineEdit(ui_evidence);
ui_evidence_name = new QLineEdit(ui_evidence);
ui_evidence_name_filter = new AOLineEditFilter();
ui_evidence_name->installEventFilter(ui_evidence_name_filter);
ui_evidence_name->setAlignment(Qt::AlignCenter);
ui_evidence_name->setFrame(false);
ui_evidence_name->setObjectName("ui_evidence_name");
@ -41,11 +43,14 @@ void Courtroom::initialize_evidence()
ui_evidence_delete = new AOButton(ui_evidence_overlay, ao_app);
ui_evidence_delete->setToolTip(tr("Destroy this piece of evidence"));
ui_evidence_delete->setObjectName("ui_evidence_delete");
ui_evidence_image_name = new AOLineEdit(ui_evidence_overlay);
ui_evidence_image_name = new QLineEdit(ui_evidence_overlay);
ui_evidence_image_name_filter = new AOLineEditFilter();
ui_evidence_image_name->installEventFilter(ui_evidence_image_name_filter);
ui_evidence_image_name->setObjectName("ui_evidence_image_name");
ui_evidence_image_button = new AOButton(ui_evidence_overlay, ao_app);
ui_evidence_image_button->setText(tr("Choose.."));
ui_evidence_image_button->setObjectName("ui_evidence_image_button");
ui_evidence_image_button->setDisabled(true);
ui_evidence_x = new AOButton(ui_evidence_overlay, ao_app);
ui_evidence_x->setToolTip(
tr("Close the evidence display/editing overlay.\n"
@ -56,50 +61,51 @@ void Courtroom::initialize_evidence()
"evidence and send them to server."));
ui_evidence_ok->setObjectName("ui_evidence_ok");
ui_evidence_description = new AOTextEdit(ui_evidence_overlay);
ui_evidence_description = new QPlainTextEdit(ui_evidence_overlay);
ui_evidence_description->setFrameStyle(QFrame::NoFrame);
ui_evidence_description->setToolTip(
tr("Double-click to edit. Press [X] to update your changes."));
tr("Click the pencil icon to edit. Press [X] to update your changes."));
ui_evidence_description->setObjectName("ui_evidence_description");
connect(ui_evidence_name, SIGNAL(returnPressed()), this,
SLOT(on_evidence_name_edited()));
connect(ui_evidence_name, SIGNAL(double_clicked()), this,
SLOT(on_evidence_name_double_clicked()));
connect(ui_evidence_left, SIGNAL(clicked()), this,
SLOT(on_evidence_left_clicked()));
connect(ui_evidence_right, SIGNAL(clicked()), this,
SLOT(on_evidence_right_clicked()));
connect(ui_evidence_present, SIGNAL(clicked()), this,
SLOT(on_evidence_present_clicked()));
connect(ui_evidence_switch, SIGNAL(clicked()), this,
SLOT(on_evidence_switch_clicked()));
connect(ui_evidence_transfer, SIGNAL(clicked()), this,
SLOT(on_evidence_transfer_clicked()));
connect(ui_evidence_save, SIGNAL(clicked()), this,
SLOT(on_evidence_save_clicked()));
connect(ui_evidence_load, SIGNAL(clicked()), this,
SLOT(on_evidence_load_clicked()));
ui_evidence_edit = new AOButton(ui_evidence_overlay, ao_app);
ui_evidence_edit->setToolTip(tr("Edit this piece of evidence."));
ui_evidence_edit->setObjectName("ui_evidence_edit");
connect(ui_evidence_delete, SIGNAL(clicked()), this,
SLOT(on_evidence_delete_clicked()));
connect(ui_evidence_image_name, SIGNAL(returnPressed()), this,
SLOT(on_evidence_image_name_edited()));
connect(ui_evidence_image_name, SIGNAL(double_clicked()), this,
SLOT(on_evidence_image_name_double_clicked()));
connect(ui_evidence_image_button, SIGNAL(clicked()), this,
SLOT(on_evidence_image_button_clicked()));
connect(ui_evidence_x, SIGNAL(clicked()), this,
SLOT(on_evidence_x_clicked()));
connect(ui_evidence_ok, SIGNAL(clicked()), this,
SLOT(on_evidence_ok_clicked()));
connect(ui_evidence_name, &QLineEdit::returnPressed, this,
&Courtroom::on_evidence_name_edited);
connect(ui_evidence_left, &AOButton::clicked, this,
&Courtroom::on_evidence_left_clicked);
connect(ui_evidence_right, &AOButton::clicked, this,
&Courtroom::on_evidence_right_clicked);
connect(ui_evidence_present, &AOButton::clicked, this,
&Courtroom::on_evidence_present_clicked);
connect(ui_evidence_switch, &AOButton::clicked, this,
&Courtroom::on_evidence_switch_clicked);
connect(ui_evidence_transfer, &AOButton::clicked, this,
&Courtroom::on_evidence_transfer_clicked);
connect(ui_evidence_save, &AOButton::clicked, this,
&Courtroom::on_evidence_save_clicked);
connect(ui_evidence_load, &AOButton::clicked, this,
&Courtroom::on_evidence_load_clicked);
connect(ui_evidence_name, SIGNAL(textChanged(QString)), this,
SLOT(on_evidence_edited()));
connect(ui_evidence_image_name, SIGNAL(textChanged(QString)), this,
SLOT(on_evidence_edited()));
connect(ui_evidence_description, SIGNAL(textChanged()), this,
SLOT(on_evidence_edited()));
connect(ui_evidence_delete, &AOButton::clicked, this,
&Courtroom::on_evidence_delete_clicked);
connect(ui_evidence_image_name, &QLineEdit::returnPressed, this,
&Courtroom::on_evidence_image_name_edited);
connect(ui_evidence_image_button, &AOButton::clicked, this,
&Courtroom::on_evidence_image_button_clicked);
connect(ui_evidence_x, &AOButton::clicked, this,
&Courtroom::on_evidence_x_clicked);
connect(ui_evidence_ok, &AOButton::clicked, this,
&Courtroom::on_evidence_ok_clicked);
connect(ui_evidence_name, &QLineEdit::textChanged, this,
&Courtroom::on_evidence_edited);
connect(ui_evidence_image_name, &QLineEdit::textChanged, this,
&Courtroom::on_evidence_image_name_edited);
connect(ui_evidence_description, &QPlainTextEdit::textChanged, this,
&Courtroom::on_evidence_edited);
connect(ui_evidence_edit, &AOButton::clicked, this, &Courtroom::on_evidence_edit_clicked);
ui_evidence->hide();
}
@ -156,6 +162,9 @@ void Courtroom::refresh_evidence()
set_size_and_pos(ui_evidence_ok, "evidence_ok");
ui_evidence_ok->set_image("evidence_ok");
set_size_and_pos(ui_evidence_edit, "evidence_edit");
ui_evidence_edit->set_image("evidence_edit");
set_size_and_pos(ui_evidence_switch, "evidence_switch");
if (current_evidence_global) {
ui_evidence_switch->set_image("evidence_global");
@ -227,12 +236,12 @@ void Courtroom::refresh_evidence()
f_evidence->set_id(n);
connect(f_evidence, SIGNAL(evidence_clicked(int)), this,
SLOT(on_evidence_clicked(int)));
connect(f_evidence, SIGNAL(evidence_double_clicked(int)), this,
SLOT(on_evidence_double_clicked(int)));
connect(f_evidence, SIGNAL(on_hover(int, bool)), this,
SLOT(on_evidence_hover(int, bool)));
connect(f_evidence, &AOEvidenceButton::evidence_clicked, this,
&Courtroom::on_evidence_clicked);
connect(f_evidence, &AOEvidenceButton::evidence_double_clicked, this,
&Courtroom::on_evidence_double_clicked);
connect(f_evidence, &AOEvidenceButton::on_hover, this,
&Courtroom::on_evidence_hover);
++x_mod_count;
@ -281,7 +290,11 @@ void Courtroom::set_evidence_list(QVector<evi_type> &p_evi_list)
msgBox->setDetailedText(tr(
"Name: %1\n"
"Image: %2\n"
"Description:\n%3").arg(local_evidence_list.at(current_evidence).name).arg(local_evidence_list.at(current_evidence).image).arg(local_evidence_list.at(current_evidence).description));
"Description:\n%3").arg(
local_evidence_list.at(current_evidence).name,
local_evidence_list.at(current_evidence).image,
local_evidence_list.at(current_evidence).description)
);
msgBox->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox->setDefaultButton(QMessageBox::LastButton);
// msgBox->setWindowModality(Qt::NonModal);
@ -309,7 +322,7 @@ void Courtroom::set_evidence_page()
ui_evidence_left->hide();
ui_evidence_right->hide();
for (AOEvidenceButton *i_button : ui_evidence_list) {
for (AOEvidenceButton *i_button : qAsConst(ui_evidence_list)) {
i_button->hide();
}
@ -368,26 +381,10 @@ void Courtroom::set_evidence_page()
void Courtroom::on_evidence_name_edited()
{
ui_evidence_name->setReadOnly(true);
if (current_evidence >= local_evidence_list.size())
return;
}
void Courtroom::on_evidence_name_double_clicked()
{
if (ui_evidence_overlay->isVisible()) {
ui_evidence_name->setReadOnly(false);
}
else {
ui_evidence_name->setReadOnly(true);
}
}
void Courtroom::on_evidence_image_name_double_clicked()
{
ui_evidence_image_name->setReadOnly(false);
}
void Courtroom::on_evidence_image_name_edited()
{
ui_evidence_image_name->setReadOnly(true);
@ -445,7 +442,7 @@ void Courtroom::on_evidence_clicked(int p_id)
ui_evidence_name->setText(local_evidence_list.at(f_real_id).name);
for (AOEvidenceButton *i_button : ui_evidence_list)
for (AOEvidenceButton *i_button : qAsConst(ui_evidence_list))
i_button->set_selected(false);
ui_evidence_list.at(p_id)->set_selected(true);
@ -469,14 +466,14 @@ void Courtroom::on_evidence_double_clicked(int p_id)
ui_evidence_description->clear();
ui_evidence_description->appendPlainText(f_evi.description);
ui_evidence_description->setReadOnly(true);
ui_evidence_description->setToolTip(tr("Double-click to edit..."));
ui_evidence_description->setToolTip(tr("Click the pencil to edit..."));
ui_evidence_name->setText(f_evi.name);
ui_evidence_name->setReadOnly(true);
ui_evidence_name->setToolTip(tr("Double-click to edit..."));
ui_evidence_name->setToolTip(tr("Click the pencil to edit..."));
ui_evidence_image_name->setText(f_evi.image);
ui_evidence_image_name->setReadOnly(true);
ui_evidence_image_name->setToolTip(tr("Double-click to edit..."));
ui_evidence_image_name->setToolTip(tr("Click the pencil to edit..."));
ui_evidence_overlay->show();
ui_evidence_ok->hide();
@ -598,6 +595,8 @@ void Courtroom::on_evidence_ok_clicked()
ui_evidence_name->setReadOnly(true);
ui_evidence_description->setReadOnly(true);
ui_evidence_image_name->setReadOnly(true);
ui_evidence_edit->show();
ui_evidence_image_button->setDisabled(true);
if (current_evidence < local_evidence_list.size()) {
evi_type f_evi = local_evidence_list.at(current_evidence);
if (current_evidence_global) {
@ -680,6 +679,22 @@ void Courtroom::on_evidence_transfer_clicked()
msgBox->exec();
}
void Courtroom::on_evidence_edit_clicked()
{
if (!ui_evidence_overlay->isVisible())
return;
if (!ui_evidence_edit->isHidden()) {
ui_evidence_name->setReadOnly(false);
ui_evidence_image_name->setReadOnly(false);
ui_evidence_description->setReadOnly(false);
ui_evidence_image_button->setDisabled(false);
ui_evidence_edit->hide();
}
else {
return;
}
}
void Courtroom::on_evidence_edited()
{
if (current_evidence >=
@ -704,6 +719,8 @@ void Courtroom::evidence_close()
ui_evidence_name->setToolTip("");
ui_evidence_image_name->setReadOnly(true);
ui_evidence_image_name->setToolTip("");
ui_evidence_edit->show();
ui_evidence_image_button->setDisabled(true);
ui_evidence_overlay->hide();
ui_ic_chat_message->setFocus();
}

View File

@ -2,6 +2,9 @@
bool file_exists(QString file_path)
{
if (file_path.isEmpty())
return false;
QFileInfo check_file(file_path);
return check_file.exists() && check_file.isFile();
@ -9,6 +12,9 @@ bool file_exists(QString file_path)
bool dir_exists(QString dir_path)
{
if (dir_path == "")
return false;
QDir check_dir(dir_path);
return check_dir.exists();

View File

@ -75,28 +75,28 @@ Lobby::Lobby(AOApplication *p_ao_app) : QMainWindow()
ui_cancel = new AOButton(ui_loading_background, ao_app);
ui_cancel->setObjectName("ui_cancel");
connect(ui_public_servers, SIGNAL(clicked()), this,
SLOT(on_public_servers_clicked()));
connect(ui_favorites, SIGNAL(clicked()), this, SLOT(on_favorites_clicked()));
connect(ui_refresh, SIGNAL(pressed()), this, SLOT(on_refresh_pressed()));
connect(ui_refresh, SIGNAL(released()), this, SLOT(on_refresh_released()));
connect(ui_add_to_fav, SIGNAL(pressed()), this,
SLOT(on_add_to_fav_pressed()));
connect(ui_add_to_fav, SIGNAL(released()), this,
SLOT(on_add_to_fav_released()));
connect(ui_connect, SIGNAL(pressed()), this, SLOT(on_connect_pressed()));
connect(ui_connect, SIGNAL(released()), this, SLOT(on_connect_released()));
connect(ui_about, SIGNAL(clicked()), this, SLOT(on_about_clicked()));
connect(ui_settings, SIGNAL(clicked()), this, SLOT(on_settings_clicked()));
connect(ui_server_list, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
SLOT(on_server_list_clicked(QTreeWidgetItem *, int)));
connect(ui_server_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
this, SLOT(on_server_list_doubleclicked(QTreeWidgetItem *, int)));
connect(ui_server_search, SIGNAL(textChanged(QString)), this,
SLOT(on_server_search_edited(QString)));
connect(ui_chatmessage, SIGNAL(returnPressed()), this,
SLOT(on_chatfield_return_pressed()));
connect(ui_cancel, SIGNAL(clicked()), ao_app, SLOT(loading_cancelled()));
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_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_search, &QLineEdit::textChanged, this,
&Lobby::on_server_search_edited);
connect(ui_chatmessage, &QLineEdit::returnPressed, this,
&Lobby::on_chatfield_return_pressed);
connect(ui_cancel, &AOButton::clicked, ao_app, &AOApplication::loading_cancelled);
ui_connect->setEnabled(false);
@ -237,6 +237,12 @@ void Lobby::set_stylesheet(QWidget *widget)
void Lobby::set_stylesheets()
{
set_stylesheet(this);
this->setStyleSheet(
"QFrame { background-color:transparent; } "
"QAbstractItemView { background-color: transparent; color: black; } "
"QLineEdit { background-color:transparent; }"
+ this->styleSheet()
);
}
void Lobby::set_font(QWidget *widget, QString p_identifier)
@ -510,7 +516,7 @@ void Lobby::list_servers()
ui_server_search->setText("");
int i = 0;
for (server_type i_server : ao_app->get_server_list()) {
for (const server_type &i_server : qAsConst(ao_app->get_server_list())) {
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_server_list);
treeItem->setData(0, Qt::DisplayRole, i);
treeItem->setText(1, i_server.name);
@ -526,7 +532,7 @@ void Lobby::list_favorites()
ui_server_list->clear();
int i = 0;
for (server_type i_server : ao_app->get_favorite_list()) {
for (const server_type &i_server : qAsConst(ao_app->get_favorite_list())) {
QTreeWidgetItem *treeItem = new QTreeWidgetItem(ui_server_list);
treeItem->setData(0, Qt::DisplayRole, i);
treeItem->setText(1, i_server.name);
@ -573,9 +579,9 @@ void Lobby::append_error(QString f_message)
void Lobby::set_player_count(int players_online, int max_players)
{
QString f_string = tr("Online: %1/%2")
.arg(QString::number(players_online))
.arg(QString::number(max_players));
QString f_string = tr("Online: %1/%2").arg(
QString::number(players_online),
QString::number(max_players));
ui_player_count->setText(f_string);
}

View File

@ -16,10 +16,10 @@ NetworkManager::NetworkManager(AOApplication *parent) : QObject(parent)
http = new QNetworkAccessManager(this);
heartbeat_timer = new QTimer(this);
connect(server_socket, SIGNAL(readyRead()), this,
SLOT(handle_server_packet()));
connect(server_socket, SIGNAL(disconnected()), ao_app,
SLOT(server_disconnected()));
connect(server_socket, &QTcpSocket::readyRead, this,
&NetworkManager::handle_server_packet);
connect(server_socket, &QTcpSocket::disconnected, ao_app,
&AOApplication::server_disconnected);
QString master_config =
ao_app->configini->value("master", "").value<QString>();

View File

@ -5,6 +5,7 @@
#include <QDir>
#include <QRegExp>
#include <QStandardPaths>
#include <QStringBuilder>
#ifdef BASE_OVERRIDE
#include "base_override.h"
@ -39,72 +40,57 @@ QString AOApplication::get_base_path()
return base_path;
}
QString AOApplication::get_data_path() { return get_base_path() + "data/"; }
QString AOApplication::get_theme_path(QString p_file, QString p_theme)
VPath AOApplication::get_theme_path(QString p_file, QString p_theme)
{
if (p_theme == "")
p_theme = current_theme;
QString path = get_base_path() + "themes/" + p_theme + "/" + p_file;
return get_case_sensitive_path(path);
return VPath("themes/" + p_theme + "/" + p_file);
}
QString AOApplication::get_character_path(QString p_char, QString p_file)
VPath AOApplication::get_character_path(QString p_char, QString p_file)
{
QString path = get_base_path() + "characters/" + p_char + "/" + p_file;
return get_case_sensitive_path(path);
return VPath("characters/" + p_char + "/" + p_file);
}
QString AOApplication::get_misc_path(QString p_misc, QString p_file)
VPath AOApplication::get_misc_path(QString p_misc, QString p_file)
{
QString path = get_base_path() + "misc/" + p_misc + "/" + p_file;
#ifndef CASE_SENSITIVE_FILESYSTEM
return path;
#else
return get_case_sensitive_path(path);
#endif
return VPath("misc/" + p_misc + "/" + p_file);
}
QString AOApplication::get_sounds_path(QString p_file)
VPath AOApplication::get_sounds_path(QString p_file)
{
QString path = get_base_path() + "sounds/general/" + p_file;
return get_case_sensitive_path(path);
return VPath("sounds/general/" + p_file);
}
QString AOApplication::get_music_path(QString p_song)
VPath AOApplication::get_music_path(QString p_song)
{
if (p_song.startsWith("http")) {
return p_song; // url
return VPath(p_song); // url
}
QString path = get_base_path() + "sounds/music/" + p_song;
return get_case_sensitive_path(path);
return VPath("sounds/music/" + p_song);
}
QString AOApplication::get_background_path(QString p_file)
VPath AOApplication::get_background_path(QString p_file)
{
QString path = get_base_path() + "background/" +
w_courtroom->get_current_background() + "/" + p_file;
if (courtroom_constructed) {
return get_case_sensitive_path(path);
return VPath("background/" + w_courtroom->get_current_background() + "/" + p_file);
}
return get_default_background_path(p_file);
}
QString AOApplication::get_default_background_path(QString p_file)
VPath AOApplication::get_default_background_path(QString p_file)
{
QString path = get_base_path() + "background/default/" + p_file;
return get_case_sensitive_path(path);
return VPath("background/default/" + p_file);
}
QString AOApplication::get_evidence_path(QString p_file)
VPath AOApplication::get_evidence_path(QString p_file)
{
QString path = get_base_path() + "evidence/" + p_file;
return get_case_sensitive_path(path);
return VPath("evidence/" + p_file);
}
QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder)
QVector<VPath> AOApplication::get_asset_paths(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder)
{
QStringList pathlist;
QVector<VPath> pathlist;
if (p_character != "")
pathlist += get_character_path(p_character, p_element); // Character folder
if (p_misc != "" && p_theme != "" && p_subtheme != "")
@ -119,7 +105,7 @@ QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, Q
pathlist += get_theme_path(p_element, p_theme); // Theme path
if (p_default_theme != "")
pathlist += get_theme_path(p_element, p_default_theme); // Default theme path
pathlist += p_element; // The path by itself
pathlist += VPath(p_element); // The path by itself
if (p_placeholder != "" && p_theme != "")
pathlist += get_theme_path(p_placeholder, p_theme); // Placeholder path
if (p_placeholder != "" && p_default_theme != "")
@ -127,52 +113,48 @@ QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, Q
return pathlist;
}
QString AOApplication::get_asset_path(QStringList pathlist)
QString AOApplication::get_asset_path(QVector<VPath> pathlist)
{
QString path;
for (QString p : pathlist) {
p = get_case_sensitive_path(p);
if (file_exists(p)) {
path = p;
break;
for (const VPath &p : pathlist) {
QString path = get_real_path(p);
if (!path.isEmpty()) {
return path;
}
}
return path;
return QString();
}
QString AOApplication::get_image_path(QStringList pathlist, bool static_image)
QString AOApplication::get_image_path(QVector<VPath> pathlist, bool static_image)
{
QString path;
for (QString p : pathlist) {
p = get_case_sensitive_path(get_image_suffix(p, static_image));
if (file_exists(p)) {
path = p;
break;
}
}
return path;
}
QString AOApplication::get_sfx_path(QStringList pathlist)
{
QString path;
for (QString p : pathlist) {
p = get_case_sensitive_path(get_sfx_suffix(p));
if (file_exists(p)) {
path = p;
break;
for (const VPath &p : pathlist) {
QString path = get_image_suffix(p, static_image);
if (!path.isEmpty()) {
return path;
}
}
return path;
return QString();
}
QString AOApplication::get_sfx_path(QVector<VPath> pathlist)
{
for (const VPath &p : pathlist) {
QString path = get_sfx_suffix(p);
if (!path.isEmpty()) {
return path;
}
}
return QString();
}
QString AOApplication::get_config_value(QString p_identifier, QString p_config, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc)
{
QString path;
// qDebug() << "got request for" << p_identifier << "in" << p_config;
for (QString p : get_asset_paths(p_config, p_theme, p_subtheme, p_default_theme, p_misc)) {
p = get_case_sensitive_path(p);
if (file_exists(p)) {
QSettings settings(p, QSettings::IniFormat);
const auto paths = get_asset_paths(p_config, p_theme, p_subtheme, p_default_theme, p_misc);
for (const VPath &p : paths) {
path = get_real_path(p);
if (!path.isEmpty()) {
QSettings settings(path, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QVariant value = settings.value(p_identifier);
if (value.type() == QVariant::StringList) {
@ -193,25 +175,22 @@ QString AOApplication::get_asset(QString p_element, QString p_theme, QString p_s
return get_asset_path(get_asset_paths(p_element, p_theme, p_subtheme, p_default_theme, p_misc, p_character, p_placeholder));
}
QString AOApplication::get_image(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder)
QString AOApplication::get_image(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder,
bool static_image)
{
return get_image_path(get_asset_paths(p_element, p_theme, p_subtheme, p_default_theme, p_misc, p_character, p_placeholder));
return get_image_path(get_asset_paths(p_element, p_theme, p_subtheme, p_default_theme, p_misc, p_character, p_placeholder), static_image);
}
QString AOApplication::get_sfx(QString p_sfx, QString p_misc, QString p_character)
{
QStringList pathlist = get_asset_paths(p_sfx, current_theme, get_subtheme(), default_theme, p_misc, p_character);
QVector<VPath> pathlist = get_asset_paths(p_sfx, current_theme, get_subtheme(), default_theme, p_misc, p_character);
pathlist += get_sounds_path(p_sfx); // Sounds folder path
return get_sfx_path(pathlist);
}
QString AOApplication::get_case_sensitive_path(QString p_file)
{
// no path traversal above base folder
if (!(p_file.startsWith(get_base_path())))
return get_base_path() + p_file;
#ifdef CASE_SENSITIVE_FILESYSTEM
#ifdef CASE_SENSITIVE_FILESYSTEM
// first, check to see if it's actually there (also serves as base case for
// recursion)
QFileInfo file(p_file);
@ -219,6 +198,7 @@ QString AOApplication::get_case_sensitive_path(QString p_file)
if (exists(p_file))
return p_file;
QString file_parent_dir = get_case_sensitive_path(file.absolutePath());
// second, does it exist in the new parent dir?
@ -226,14 +206,20 @@ QString AOApplication::get_case_sensitive_path(QString p_file)
return file_parent_dir + "/" + file_basename;
// last resort, dirlist parent dir and find case insensitive match
QRegExp file_rx =
QRegExp(file_basename, Qt::CaseInsensitive, QRegExp::FixedString);
QStringList files = QDir(file_parent_dir).entryList();
int result = files.indexOf(file_rx);
if (!dir_listing_exist_cache.contains(qHash(file_parent_dir))) {
QStringList files = QDir(file_parent_dir).entryList();
for (const QString &file : files) {
dir_listing_cache.insert(qHash(file_parent_dir % QChar('/') % file.toLower()), file);
}
dir_listing_exist_cache.insert(qHash(file_parent_dir));
}
QString found_file = dir_listing_cache.value(
qHash(file_parent_dir % QChar('/') % file_basename.toLower()));
if (result != -1)
return file_parent_dir + "/" + files.at(result);
if (!found_file.isEmpty()) {
return file_parent_dir + "/" + found_file;
}
// if nothing is found, let the caller handle the missing file
return file_parent_dir + "/" + file_basename;
@ -241,3 +227,81 @@ QString AOApplication::get_case_sensitive_path(QString p_file)
return p_file;
#endif
}
QString AOApplication::get_real_path(const VPath &vpath) {
// Try cache first
QString phys_path = asset_lookup_cache.value(qHash(vpath));
if (!phys_path.isEmpty() && exists(phys_path)) {
return phys_path;
}
// Cache miss; try all known mount paths
QStringList bases = get_mount_paths();
bases.push_front(get_base_path());
for (const QString &base : bases) {
QDir baseDir(base);
QString path = baseDir.absoluteFilePath(vpath.toQString());
if (!path.startsWith(baseDir.absolutePath())) {
qWarning() << "invalid path" << path << "(path is outside vfs)";
break;
}
path = get_case_sensitive_path(path);
if (exists(path)) {
asset_lookup_cache.insert(qHash(vpath), path);
return path;
}
}
// Not found in mount paths; check if the file is remote
QString remotePath = vpath.toQString();
if (remotePath.startsWith("http:") || remotePath.startsWith("https:")) {
return remotePath;
}
// File or directory not found
return QString();
}
// Special case of get_real_path where multiple suffixes need to be tried
// on each mount path.
QString AOApplication::get_real_suffixed_path(const VPath &vpath,
const QStringList &suffixes) {
// Try cache first
QString phys_path = asset_lookup_cache.value(qHash(vpath));
if (!phys_path.isEmpty() && exists(phys_path)) {
for (const QString &suffix : suffixes) { // make sure cached asset is the right type
if (phys_path.endsWith(suffix, Qt::CaseInsensitive))
return phys_path;
}
}
// Cache miss; try each suffix on all known mount paths
QStringList bases = get_mount_paths();
bases.push_front(get_base_path());
for (const QString &base : bases) {
for (const QString &suffix : suffixes) {
QDir baseDir(base);
QString path = baseDir.absoluteFilePath(vpath.toQString() + suffix);
if (!path.startsWith(baseDir.absolutePath())) {
qWarning() << "invalid path" << path << "(path is outside vfs)";
break;
}
path = get_case_sensitive_path(path);
if (exists(path)) {
asset_lookup_cache.insert(qHash(vpath), path);
return path;
}
}
}
// File or directory not found
return QString();
}
void AOApplication::invalidate_lookup_cache() {
asset_lookup_cache.clear();
dir_listing_cache.clear();
dir_listing_exist_cache.clear();
}

View File

@ -9,7 +9,7 @@ ScrollText::ScrollText(QWidget *parent) : QWidget(parent), scrollPos(0)
setSeparator(" --- ");
connect(&timer, SIGNAL(timeout()), this, SLOT(timer_timeout()));
connect(&timer, &QTimer::timeout, this, &ScrollText::timer_timeout);
timer.setInterval(50);
}

View File

@ -89,6 +89,12 @@ bool AOApplication::get_log_timestamp()
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 =
@ -130,6 +136,11 @@ QStringList AOApplication::get_call_words()
return get_list_file(get_base_path() + "callwords.ini");
}
QStringList AOApplication::get_list_file(VPath path)
{
return get_list_file(get_real_path(path));
}
QStringList AOApplication::get_list_file(QString p_file)
{
QStringList return_value;
@ -279,6 +290,12 @@ QVector<server_type> AOApplication::read_serverlist_txt()
return f_server_list;
}
QString AOApplication::read_design_ini(QString p_identifier,
VPath p_design_path)
{
return read_design_ini(p_identifier, get_real_path(p_design_path));
}
QString AOApplication::read_design_ini(QString p_identifier,
QString p_design_path)
{
@ -448,12 +465,14 @@ QString AOApplication::get_chat_markup(QString p_identifier, QString p_chat)
return value.toUtf8();
// Backwards ass compatibility
QStringList backwards_paths{get_theme_path("misc/" + p_chat + "/config.ini"),
get_base_path() + "misc/" + p_chat +
"/config.ini",
get_theme_path("misc/default/config.ini"),
get_base_path() + "misc/default/config.ini"};
for (const QString &p : backwards_paths) {
QVector<VPath> backwards_paths {
get_theme_path("misc/" + p_chat + "/config.ini"),
VPath("misc/" + p_chat + "/config.ini"),
get_theme_path("misc/default/config.ini"),
VPath("misc/default/config.ini")
};
for (const VPath &p : backwards_paths) {
QString value = read_design_ini(p_identifier, p);
if (!value.isEmpty()) {
return value.toUtf8();
@ -490,36 +509,21 @@ QString AOApplication::get_court_sfx(QString p_identifier, QString p_misc)
return "";
}
QString AOApplication::get_sfx_suffix(QString sound_to_check)
QString AOApplication::get_sfx_suffix(VPath sound_to_check)
{
if (file_exists(sound_to_check))
return sound_to_check;
if (file_exists(sound_to_check + ".opus"))
return sound_to_check + ".opus";
if (file_exists(sound_to_check + ".ogg"))
return sound_to_check + ".ogg";
if (file_exists(sound_to_check + ".mp3"))
return sound_to_check + ".mp3";
if (file_exists(sound_to_check + ".mp4"))
return sound_to_check + ".mp4";
return sound_to_check + ".wav";
return get_real_suffixed_path(sound_to_check,
{".opus", ".ogg", ".mp3", ".wav" });
}
QString AOApplication::get_image_suffix(QString path_to_check, bool static_image)
QString AOApplication::get_image_suffix(VPath path_to_check, bool static_image)
{
if (file_exists(path_to_check))
return path_to_check;
// A better method would to actually use AOImageReader and see if these images have more than 1 frame.
// However, that might not be performant.
QStringList suffixes {};
if (!static_image) {
if (file_exists(path_to_check + ".webp"))
return path_to_check + ".webp";
if (file_exists(path_to_check + ".apng"))
return path_to_check + ".apng";
if (file_exists(path_to_check + ".gif"))
return path_to_check + ".gif";
suffixes.append({ ".webp", ".apng", ".gif" });
}
return path_to_check + ".png";
suffixes.append(".png");
return get_real_suffixed_path(path_to_check, suffixes);
}
// returns whatever is to the right of "search_line =" within target_tag and
@ -528,7 +532,7 @@ QString AOApplication::get_image_suffix(QString path_to_check, bool static_image
QString AOApplication::read_char_ini(QString p_char, QString p_search_line,
QString target_tag)
{
QSettings settings(get_character_path(p_char, "char.ini"),
QSettings settings(get_real_path(get_character_path(p_char, "char.ini")),
QSettings::IniFormat);
settings.beginGroup(target_tag);
settings.setIniCodec("UTF-8");
@ -540,7 +544,7 @@ QString AOApplication::read_char_ini(QString p_char, QString p_search_line,
void AOApplication::set_char_ini(QString p_char, QString value,
QString p_search_line, QString target_tag)
{
QSettings settings(get_character_path(p_char, "char.ini"),
QSettings settings(get_real_path(get_character_path(p_char, "char.ini")),
QSettings::IniFormat);
settings.beginGroup(target_tag);
settings.setValue(p_search_line, value);
@ -548,10 +552,10 @@ void AOApplication::set_char_ini(QString p_char, QString value,
}
// returns all the values of target_tag
QStringList AOApplication::read_ini_tags(QString p_path, QString target_tag)
QStringList AOApplication::read_ini_tags(VPath p_path, QString target_tag)
{
QStringList r_values;
QSettings settings(p_path, QSettings::IniFormat);
QSettings settings(get_real_path(p_path), QSettings::IniFormat);
settings.setIniCodec("UTF-8");
if (!target_tag.isEmpty())
settings.beginGroup(target_tag);
@ -1096,6 +1100,11 @@ 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>()