Merge pull request #6398 from aerusso/pulls/settings-autosave-timer

Periodically save settings
This commit is contained in:
John Maguire 2019-09-19 10:20:05 +01:00 committed by GitHub
commit 88131ec5f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 185 additions and 101 deletions

View File

@ -20,6 +20,9 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QSettings>
#include <QTimer>
#include "application.h"
#include "config.h"
@ -67,7 +70,8 @@ bool Application::kIsPortable = false;
class ApplicationImpl {
public:
ApplicationImpl(Application* app)
: tag_reader_client_([=]() {
: settings_timer_(app),
tag_reader_client_([=]() {
TagReaderClient* client = new TagReaderClient(app);
app->MoveToNewThread(client);
client->Start();
@ -150,6 +154,9 @@ class ApplicationImpl {
}) {
}
QTimer settings_timer_;
QSettings settings_;
Lazy<TagReaderClient> tag_reader_client_;
Lazy<Database> database_;
Lazy<AlbumCoverLoader> album_cover_loader_;
@ -188,6 +195,10 @@ Application::Application(QObject* parent)
// TODO(John Maguire): Make this not a weird singleton.
tag_reader_client();
p_->settings_timer_.setInterval(1000);
p_->settings_timer_.setSingleShot(true);
connect(&(p_->settings_timer_), SIGNAL(timeout()), SLOT(SaveSettings_()));
}
Application::~Application() {
@ -229,6 +240,8 @@ QString Application::language_without_region() const {
return language_name_;
}
void Application::SaveSettings_() { emit SaveSettings(&(p_->settings_)); }
void Application::ReloadSettings() { emit SettingsChanged(); }
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
@ -326,3 +339,5 @@ TagReaderClient* Application::tag_reader_client() const {
TaskManager* Application::task_manager() const {
return p_->task_manager_.get();
}
void Application::DirtySettings() { p_->settings_timer_.start(); }

View File

@ -28,6 +28,8 @@
#include "ui/settingsdialog.h"
class QSettings;
class AlbumCoverLoader;
class Appearance;
class ApplicationImpl;
@ -98,6 +100,8 @@ class Application : public QObject {
TagReaderClient* tag_reader_client() const;
TaskManager* task_manager() const;
void DirtySettings();
void MoveToNewThread(QObject* object);
void MoveToThread(QObject* object, QThread* thread);
@ -109,8 +113,12 @@ class Application : public QObject {
signals:
void ErrorAdded(const QString& message);
void SettingsChanged();
void SaveSettings(QSettings* settings);
void SettingsDialogRequested(SettingsDialog::Page page);
private slots:
void SaveSettings_();
private:
QString language_name_;
std::unique_ptr<ApplicationImpl> p_;

View File

@ -430,6 +430,7 @@ int main(int argc, char* argv[]) {
QtConcurrent::run(&ParseAProto);
Application app;
QObject::connect(&a, SIGNAL(aboutToQuit()), &app, SLOT(SaveSettings_()));
app.set_language_name(language);
// Network proxy

View File

@ -16,6 +16,7 @@
*/
#include "core/appearance.h"
#include "core/application.h"
#include "core/logging.h"
#include "core/player.h"
#include "core/timeconstants.h"
@ -43,6 +44,7 @@ const int PlaylistContainer::kFilterDelayPlaylistSizeThreshold = 5000;
PlaylistContainer::PlaylistContainer(QWidget* parent)
: QWidget(parent),
app_(nullptr),
ui_(new Ui_PlaylistContainer),
manager_(nullptr),
undo_(nullptr),
@ -52,7 +54,8 @@ PlaylistContainer::PlaylistContainer(QWidget* parent)
tab_bar_visible_(false),
tab_bar_animation_(new QTimeLine(500, this)),
no_matches_label_(nullptr),
filter_timer_(new QTimer(this)) {
filter_timer_(new QTimer(this)),
dirty_(false) {
ui_->setupUi(this);
no_matches_label_ = new QLabel(ui_->playlist);
@ -96,6 +99,7 @@ PlaylistContainer::PlaylistContainer(QWidget* parent)
ui_->tab_bar->setMaximumHeight(0);
// Connections
connect(ui_->tab_bar, SIGNAL(currentChanged(int)), SLOT(DirtyTabBar()));
connect(ui_->tab_bar, SIGNAL(Save(int)), SLOT(SavePlaylist(int)));
// set up timer for delayed filter updates
@ -111,10 +115,17 @@ PlaylistContainer::PlaylistContainer(QWidget* parent)
}
PlaylistContainer::~PlaylistContainer() {
Save();
delete ui_;
}
void PlaylistContainer::SetApplication(Application* app) {
Q_ASSERT(app);
app_ = app;
SetManager(app_->playlist_manager());
ui_->playlist->SetApplication(app_);
connect(app_, SIGNAL(SaveSettings(QSettings*)), SLOT(Save(QSettings*)));
}
PlaylistView* PlaylistContainer::view() const { return ui_->playlist; }
void PlaylistContainer::SetActions(QAction* new_playlist,
@ -334,10 +345,18 @@ void PlaylistContainer::GoToPreviousPlaylistTab() {
manager_->SetCurrentPlaylist(id_previous);
}
void PlaylistContainer::Save() {
if (starting_up_) return;
void PlaylistContainer::DirtyTabBar() {
dirty_ = true;
app_->DirtySettings();
}
settings_.setValue("current_playlist", ui_->tab_bar->current_id());
void PlaylistContainer::Save(QSettings* settings_) {
if (starting_up_ || !dirty_) return;
dirty_ = false;
settings_->beginGroup(kSettingsGroup);
settings_->setValue("current_playlist", ui_->tab_bar->current_id());
settings_->endGroup();
}
void PlaylistContainer::SetTabBarVisible(bool visible) {

View File

@ -23,6 +23,7 @@
class Ui_PlaylistContainer;
class Application;
class LineEditInterface;
class Playlist;
class PlaylistManager;
@ -41,6 +42,7 @@ class PlaylistContainer : public QWidget {
static const char* kSettingsGroup;
void SetApplication(Application* app);
void SetActions(QAction* new_playlist, QAction* load_playlist,
QAction* save_playlist, QAction* next_playlist,
QAction* previous_playlist);
@ -83,7 +85,8 @@ signals:
void ActivePaused();
void ActiveStopped();
void Save();
void DirtyTabBar();
void Save(QSettings* settings_);
void SetTabBarVisible(bool visible);
void SetTabBarHeight(int height);
@ -103,6 +106,7 @@ signals:
static const int kFilterDelayMs;
static const int kFilterDelayPlaylistSizeThreshold;
Application* app_;
Ui_PlaylistContainer* ui_;
PlaylistManager* manager_;
@ -119,6 +123,8 @@ signals:
QLabel* no_matches_label_;
QTimer* filter_timer_;
bool dirty_;
};
#endif // PLAYLISTCONTAINER_H

View File

@ -135,6 +135,8 @@ PlaylistView::PlaylistView(QWidget* parent)
cached_current_row_row_(-1),
drop_indicator_row_(-1),
drag_over_(false),
dirty_geometry_(false),
dirty_settings_(false),
dynamic_controls_(new DynamicPlaylistControls(this)) {
setHeader(header_);
header_->setSectionsMovable(true);
@ -153,12 +155,13 @@ PlaylistView::PlaylistView(QWidget* parent)
currenttrack_pause_ =
currenttrack_pause.pixmap(currenttrack_pause.actualSize(QSize(32, 32)));
connect(header_, SIGNAL(sectionResized(int, int, int)), SLOT(SaveGeometry()));
connect(header_, SIGNAL(sectionMoved(int, int, int)), SLOT(SaveGeometry()));
connect(header_, SIGNAL(sectionResized(int, int, int)),
SLOT(DirtyGeometry()));
connect(header_, SIGNAL(sectionMoved(int, int, int)), SLOT(DirtyGeometry()));
connect(header_, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
SLOT(SaveGeometry()));
SLOT(DirtyGeometry()));
connect(header_, SIGNAL(SectionVisibilityChanged(int, bool)),
SLOT(SaveGeometry()));
SLOT(DirtyGeometry()));
connect(header_, SIGNAL(SectionRatingLockStatusChanged(bool)),
SLOT(SetRatingLockStatus(bool)));
connect(header_, SIGNAL(sectionResized(int, int, int)),
@ -167,7 +170,7 @@ PlaylistView::PlaylistView(QWidget* parent)
SLOT(InvalidateCachedCurrentPixmap()));
connect(header_, SIGNAL(SectionVisibilityChanged(int, bool)),
SLOT(InvalidateCachedCurrentPixmap()));
connect(header_, SIGNAL(StretchEnabledChanged(bool)), SLOT(SaveSettings()));
connect(header_, SIGNAL(StretchEnabledChanged(bool)), SLOT(DirtySettings()));
connect(header_, SIGNAL(StretchEnabledChanged(bool)),
SLOT(StretchChanged(bool)));
connect(header_, SIGNAL(MouseEntered()), SLOT(RatingHoverOut()));
@ -196,7 +199,6 @@ PlaylistView::PlaylistView(QWidget* parent)
}
PlaylistView::~PlaylistView() {
SaveGeometry();
delete style_;
}
@ -210,6 +212,10 @@ void PlaylistView::SetApplication(Application* app) {
connect(app_->player(), SIGNAL(Playing()), SLOT(StartGlowing()));
connect(app_->player(), SIGNAL(Stopped()), SLOT(StopGlowing()));
connect(app_->player(), SIGNAL(Stopped()), SLOT(PlayerStopped()));
connect(app_, SIGNAL(SaveSettings(QSettings*)),
SLOT(SaveGeometry(QSettings*)));
connect(app_, SIGNAL(SaveSettings(QSettings*)),
SLOT(SaveSettings(QSettings*)));
}
void PlaylistView::SetItemDelegates(LibraryBackend* backend) {
@ -416,13 +422,19 @@ void PlaylistView::LoadRatingLockStatus() {
ratings_locked_ = s.value("RatingLocked", false).toBool();
}
void PlaylistView::SaveGeometry() {
if (read_only_settings_ || !header_loaded_) return;
void PlaylistView::DirtyGeometry() {
dirty_geometry_ = true;
app_->DirtySettings();
}
QSettings settings;
settings.beginGroup(Playlist::kSettingsGroup);
settings.setValue("state", header_->SaveState());
settings.setValue("state_version", kStateVersion);
void PlaylistView::SaveGeometry(QSettings* settings) {
if (!dirty_geometry_ || read_only_settings_ || !header_loaded_) return;
dirty_geometry_ = false;
settings->beginGroup(Playlist::kSettingsGroup);
settings->setValue("state", header_->SaveState());
settings->setValue("state_version", kStateVersion);
settings->endGroup();
}
void PlaylistView::SetRatingLockStatus(bool state) {
@ -1179,20 +1191,28 @@ void PlaylistView::ReloadSettings() {
setEditTriggers(editTriggers() | QAbstractItemView::SelectedClicked);
}
void PlaylistView::SaveSettings() {
if (read_only_settings_) return;
void PlaylistView::DirtySettings() {
dirty_settings_ = true;
app_->DirtySettings();
}
QSettings s;
s.beginGroup(Playlist::kSettingsGroup);
s.setValue("glow_effect", glow_enabled_);
s.setValue("column_alignments", QVariant::fromValue(column_alignment_));
s.setValue(kSettingBackgroundImageType, background_image_type_);
void PlaylistView::SaveSettings(QSettings* settings) {
if (!dirty_settings_ || read_only_settings_) return;
dirty_settings_ = false;
settings->beginGroup(Playlist::kSettingsGroup);
settings->setValue("glow_effect", glow_enabled_);
settings->setValue("column_alignments",
QVariant::fromValue(column_alignment_));
settings->setValue(kSettingBackgroundImageType, background_image_type_);
settings->endGroup();
}
void PlaylistView::StretchChanged(bool stretch) {
setHorizontalScrollBarPolicy(stretch ? Qt::ScrollBarAlwaysOff
: Qt::ScrollBarAsNeeded);
SaveGeometry();
dirty_geometry_ = true;
app_->DirtySettings();
}
void PlaylistView::DynamicModeChanged(bool dynamic) {
@ -1261,7 +1281,8 @@ void PlaylistView::SetColumnAlignment(int section, Qt::Alignment alignment) {
column_alignment_[section] = alignment;
emit ColumnAlignmentChanged(column_alignment_);
SaveSettings();
dirty_settings_ = true;
app_->DirtySettings();
}
Qt::Alignment PlaylistView::column_alignment(int section) const {

View File

@ -145,7 +145,9 @@ signals:
private slots:
void LoadGeometry();
void LoadRatingLockStatus();
void SaveGeometry();
void DirtyGeometry();
void DirtySettings();
void SaveGeometry(QSettings* settings);
void SetRatingLockStatus(bool state);
void GlowIntensityChanged();
void InhibitAutoscrollTimeout();
@ -153,7 +155,7 @@ signals:
void InvalidateCachedCurrentPixmap();
void PlaylistDestroyed();
void SaveSettings();
void SaveSettings(QSettings* s);
void StretchChanged(bool stretch);
void RatingHoverIn(const QModelIndex& index, const QPoint& pos);
@ -251,6 +253,9 @@ signals:
int drop_indicator_row_;
bool drag_over_;
bool dirty_geometry_;
bool dirty_settings_;
bool ratings_locked_; // To store Ratings section lock status
DynamicPlaylistControls* dynamic_controls_;

View File

@ -223,6 +223,8 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
track_position_timer_(new QTimer(this)),
track_slider_timer_(new QTimer(this)),
initialized_(false),
dirty_geometry_(false),
dirty_playback_(false),
saved_playback_position_(0),
saved_playback_state_(Engine::Empty),
doubleclick_addmode_(AddBehaviour_Append),
@ -258,6 +260,9 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
connect(global_search_view_, SIGNAL(AddToPlaylist(QMimeData*)),
SLOT(AddToPlaylist(QMimeData*)));
// Set up the settings group early
settings_.beginGroup(kSettingsGroup);
// Add tabs to the fancy tab widget
ui_->tabs->addTab(global_search_view_,
IconLoader::Load("search", IconLoader::Base),
@ -292,7 +297,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
ui_->tabs->setBackgroundPixmap(QPixmap(":/sidebar_background.png"));
// Do this only after all default tabs have been added
ui_->tabs->loadSettings(kSettingsGroup);
ui_->tabs->loadSettings(settings_);
track_position_timer_->setInterval(kTrackPositionUpdateTimeMs);
connect(track_position_timer_, SIGNAL(timeout()),
@ -301,6 +306,9 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
connect(track_slider_timer_, SIGNAL(timeout()),
SLOT(UpdateTrackSliderPosition()));
connect(app_, SIGNAL(SaveSettings(QSettings*)),
SLOT(SaveSettings(QSettings*)));
// Start initialising the player
qLog(Debug) << "Initialising player";
app_->player()->Init();
@ -317,8 +325,7 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
connect(ui_->playlist, SIGNAL(ViewSelectionModelChanged()),
SLOT(PlaylistViewSelectionModelChanged()));
ui_->playlist->SetManager(app_->playlist_manager());
ui_->playlist->view()->SetApplication(app_);
ui_->playlist->SetApplication(app_);
library_view_->view()->setModel(library_sort_model_);
library_view_->view()->SetApplication(app_);
@ -977,7 +984,6 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
// Load settings
qLog(Debug) << "Loading settings";
settings_.beginGroup(kSettingsGroup);
// Set last used geometry to position window on the correct monitor
// Set window state only if the window was last maximized
@ -1064,13 +1070,11 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
if (!options.contains_play_options()) LoadPlaybackStatus();
initialized_ = true;
SaveGeometry();
qLog(Debug) << "Started";
}
MainWindow::~MainWindow() {
SaveGeometry();
delete ui_;
}
@ -1085,18 +1089,15 @@ void MainWindow::ReloadSettings() {
show();
#endif
QSettings s;
s.beginGroup(kSettingsGroup);
doubleclick_addmode_ =
AddBehaviour(s.value("doubleclick_addmode", AddBehaviour_Append).toInt());
doubleclick_addmode_ = AddBehaviour(
settings_.value("doubleclick_addmode", AddBehaviour_Append).toInt());
doubleclick_playmode_ = PlayBehaviour(
s.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt());
doubleclick_playlist_addmode_ =
PlaylistAddBehaviour(s.value("doubleclick_playlist_addmode",
PlaylistAddBehaviour_Play).toInt());
menu_playmode_ =
PlayBehaviour(s.value("menu_playmode", PlayBehaviour_IfStopped).toInt());
settings_.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt());
doubleclick_playlist_addmode_ = PlaylistAddBehaviour(
settings_.value("doubleclick_playlist_addmode", PlaylistAddBehaviour_Play)
.toInt());
menu_playmode_ = PlayBehaviour(
settings_.value("menu_playmode", PlayBehaviour_IfStopped).toInt());
bool show_sidebar = settings_.value("show_sidebar", true).toBool();
ui_->sidebar_layout->setVisible(show_sidebar);
@ -1278,54 +1279,61 @@ void MainWindow::ScrobbleButtonVisibilityChanged(bool value) {
}
}
void MainWindow::changeEvent(QEvent*) {
void MainWindow::SaveSettings(QSettings* settings) {
if (!initialized_) return;
SaveGeometry();
settings->beginGroup(kSettingsGroup);
if (dirty_geometry_) SaveGeometry(settings);
if (dirty_playback_) SavePlaybackStatus(settings);
settings->endGroup();
}
void MainWindow::changeEvent(QEvent*) {
dirty_geometry_ = true;
app_->DirtySettings();
}
void MainWindow::resizeEvent(QResizeEvent*) {
if (!initialized_) return;
SaveGeometry();
dirty_geometry_ = true;
app_->DirtySettings();
}
void MainWindow::SaveGeometry() {
void MainWindow::SaveGeometry(QSettings* settings) {
if (!initialized_) return;
dirty_geometry_ = false;
was_maximized_ = isMaximized();
settings_.setValue("maximized", was_maximized_);
settings->setValue("maximized", was_maximized_);
// Save the geometry only when mainwindow is not in maximized state
if (!was_maximized_) {
settings_.setValue("geometry", saveGeometry());
settings->setValue("geometry", saveGeometry());
}
settings_.setValue("splitter_state", ui_->splitter->saveState());
settings_.setValue("current_tab", ui_->tabs->currentIndex());
settings_.setValue("tab_mode", ui_->tabs->mode());
settings->setValue("splitter_state", ui_->splitter->saveState());
settings->setValue("current_tab", ui_->tabs->currentIndex());
settings->setValue("tab_mode", ui_->tabs->mode());
ui_->tabs->saveSettings(kSettingsGroup);
// Leaving this here for now
ui_->tabs->saveSettings(settings);
}
void MainWindow::SavePlaybackStatus() {
QSettings settings;
settings.beginGroup(MainWindow::kSettingsGroup);
settings.setValue("playback_state", app_->player()->GetState());
void MainWindow::SavePlaybackStatus(QSettings* settings) {
dirty_playback_ = false;
settings->setValue("playback_state", app_->player()->GetState());
if (app_->player()->GetState() == Engine::Playing ||
app_->player()->GetState() == Engine::Paused) {
settings.setValue(
settings->setValue(
"playback_position",
app_->player()->engine()->position_nanosec() / kNsecPerSec);
} else {
settings.setValue("playback_position", 0);
settings->setValue("playback_position", 0);
}
}
void MainWindow::LoadPlaybackStatus() {
QSettings settings;
settings.beginGroup(MainWindow::kSettingsGroup);
bool resume_playback =
settings.value("resume_playback_after_start", false).toBool();
settings_.value("resume_playback_after_start", false).toBool();
saved_playback_state_ = static_cast<Engine::State>(
settings.value("playback_state", Engine::Empty).toInt());
saved_playback_position_ = settings.value("playback_position", 0).toDouble();
settings_.value("playback_state", Engine::Empty).toInt());
saved_playback_position_ = settings_.value("playback_position", 0).toDouble();
if (!resume_playback || saved_playback_state_ == Engine::Empty ||
saved_playback_state_ == Engine::Idle) {
return;
@ -1433,12 +1441,10 @@ void MainWindow::StopAfterCurrent() {
}
void MainWindow::closeEvent(QCloseEvent* event) {
QSettings s;
s.beginGroup(kSettingsGroup);
bool keep_running(false);
if (tray_icon_)
keep_running = s.value("keeprunning", tray_icon_->IsVisible()).toBool();
keep_running =
settings_.value("keeprunning", tray_icon_->IsVisible()).toBool();
if (keep_running && event->spontaneous()) {
event->ignore();
@ -2794,10 +2800,13 @@ bool MainWindow::winEvent(MSG* msg, long*) {
#endif // Q_OS_WIN32
void MainWindow::Exit() {
SaveGeometry();
SavePlaybackStatus();
// FIXME: This may add an extra write.
dirty_playback_ = true;
settings_.setValue("show_sidebar",
ui_->action_toggle_show_sidebar->isChecked());
settings_.endGroup();
SaveSettings(&settings_);
settings_.sync();
if (app_->player()->engine()->is_fadeout_enabled()) {
// To shut down the application when fadeout will be finished

View File

@ -151,6 +151,7 @@ signals:
private slots:
void FilePathChanged(const QString& path);
void SaveSettings(QSettings* settings);
void MediaStopped();
void MediaPaused();
void MediaPlaying();
@ -266,8 +267,8 @@ signals:
void OpenSettingsDialogAtPage(SettingsDialog::Page page);
void ShowSongInfoConfig();
void SaveGeometry();
void SavePlaybackStatus();
void SaveGeometry(QSettings* settings);
void SavePlaybackStatus(QSettings* settings);
void LoadPlaybackStatus();
void ResumePlayback();
@ -380,6 +381,10 @@ signals:
QSettings settings_;
bool initialized_;
bool dirty_geometry_;
bool dirty_playback_;
bool was_maximized_;
int saved_playback_position_;
Engine::State saved_playback_state_;

View File

@ -290,33 +290,27 @@ FancyTabWidget::FancyTabWidget(QWidget* parent) : QTabWidget(parent),
connect(tabBar, SIGNAL(currentChanged(int)), this, SLOT(currentTabChanged(int)));
}
void FancyTabWidget::loadSettings(const char *kSettingsGroup) {
QSettings settings;
settings.beginGroup(kSettingsGroup);
void FancyTabWidget::loadSettings(const QSettings& settings) {
for (int i = 0; i < count(); i++) {
int originalIndex = tabBar()->tabData(i).toInt();
QString k = "tab_index_" + QString::number(originalIndex);
for(int i =0;i<count();i++) {
int originalIndex = tabBar()->tabData(i).toInt();
std::string k = "tab_index_" + std::to_string(originalIndex);
int newIndex = settings.value(k, i).toInt();
int newIndex = settings.value(QString::fromStdString(k), i).toInt();
if(newIndex >= 0)
tabBar()->moveTab(i,newIndex);
else
removeTab(i); // Does not delete page
}
if (newIndex >= 0)
tabBar()->moveTab(i, newIndex);
else
removeTab(i); // Does not delete page
}
}
void FancyTabWidget::saveSettings(const char *kSettingsGroup) {
QSettings settings;
settings.beginGroup(kSettingsGroup);
void FancyTabWidget::saveSettings(QSettings* settings) {
for (int i = 0; i < count(); i++) {
int originalIndex = tabBar()->tabData(i).toInt();
QString k = "tab_index_" + QString::number(originalIndex);
for(int i =0;i<count();i++) {
int originalIndex = tabBar()->tabData(i).toInt();
std::string k = "tab_index_" + std::to_string(originalIndex);
settings.setValue(QString::fromStdString(k), i);
}
settings->setValue(k, i);
}
}

View File

@ -25,6 +25,7 @@
class QActionGroup;
class QMenu;
class QSettings;
class QSignalMapper;
namespace Core {
@ -43,8 +44,8 @@ class FancyTabWidget : public QTabWidget {
void setBackgroundPixmap(const QPixmap& pixmap);
void addSpacer();
void loadSettings(const char *);
void saveSettings(const char *);
void loadSettings(const QSettings&);
void saveSettings(QSettings*);
// Values are persisted - only add to the end
enum Mode {
Mode_None = 0,