Merge branch 'master' into feature/http-ms
This commit is contained in:
		
						commit
						b0e9f8dbe5
					
				@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
@ -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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
@ -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
									
								
							
							
						
						
									
										36
									
								
								include/eventfilters.h
									
									
									
									
									
										Normal 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
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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("");
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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); }
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 =
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										139
									
								
								src/aolayer.cpp
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								src/aolayer.cpp
									
									
									
									
									
								
							@ -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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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__))
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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); }
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
@ -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) {
 | 
			
		||||
@ -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));
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
#include <QElapsedTimer>
 | 
			
		||||
#include <QMessageBox>
 | 
			
		||||
#include <QTimer>
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										153
									
								
								src/evidence.cpp
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								src/evidence.cpp
									
									
									
									
									
								
							@ -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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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>();
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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>()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user