2010-08-03 26 views
3

Sur Mac et Gnome, les applications natives utilisent une boîte de dialogue de préférences d'application qui applique immédiatement les paramètres sélectionnés lorsqu'ils sont sélectionnés. Sur Windows et (je pense) KDE, les préférences sont appliquées seulement quand un bouton "Appliquer" ou "OK" est pressé.Boîte de dialogue des préférences natives de plate-forme avec Qt sur Mac, Gnome, KDE et Windows

Y a-t-il des goodies Qt intégrés pour le faire pour vous, ou avez-vous d'inclure plusieurs #ifdef « s dans le code de dialogue pour gérer ce (Q_WS_WIN, Q_WS_MAC, Q_WS_X11)?

Si vous avez déjà fait quelque chose comme ça (même en utilisant #ifdef), pourriez-vous partager le code du squelette quant à la façon dont vous l'avez retiré?

Répondre

0

On dirait que vous devez faire tourner le vôtre. Voici les parties importantes de notre solution. Cela pourrait probablement être généralisé si quelqu'un est si enclin. Je suis également capable d'assumer certaines choses à cause de nos règles métier qui peuvent casser d'autres applications. La bascule est une macro qui peut être définie au moment de la compilation: YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY

preferences_dialog.h

class PreferencesDialog : public QDialog { 
    Q_OBJECT 

public: 
    explicit PreferencesDialog(... various arguments ..., 
          QWidget *parent); 
private slots: 
    void ModifyMapLanguages(); 

private: 
    void ApplyLanguageChanges(const QList<Language> &languages, 
          const QHash<LanguageKey, LanguageKey> &renames); 
    void Initialize(); 

#ifndef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY 
public slots: 
    void accept(); 
private slots: 
    void ApplyDialog(); 
private: 
    QList<Language> pending_languages_; 
    QHash<LanguageKey, LanguageKey> pending_language_renames_; 
#endif 
}; 

preferences_dialog.cpp

#include "forms/preferences_dialog.h" 
#include "ui_preferences_dialog.h" 

PreferencesDialog::PreferencesDialog(... various arguments ..., 
            QWidget *parent) : 
    QDialog(parent), 
    ... various initializers ... { 
    ui->setupUi(this); 
    Initialize(); 
} 

void PreferencesDialog::ApplyLanguageChanges(
    const QList<Language> &languages, 
    const QHash<LanguageKey, LanguageKey> &renames) { 
    // Do the actual changes here, whether immediate or postponed 
} 

void PreferencesDialog::Initialize() { 
    // Disable the minimize and maximize buttons. 
    Qt::WindowFlags flags = this->windowFlags(); 
    flags |= Qt::CustomizeWindowHint; 
    flags &= ~Qt::WindowMinMaxButtonsHint; 
    setWindowFlags(flags); 

// buttons is the QDialogButtonBox with Ok, Cancel, and Apply buttons 
#ifdef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY  
    ui->buttons->setVisible(false); 
#else 
    QPushButton *apply_button = ui->buttons->button(QDialogButtonBox::Apply); 
    connect(apply_button, SIGNAL(clicked()), SLOT(ApplyDialog())); 
#endif  
} 

void PreferencesDialog::ModifyMapLanguages() { 
    // Get the changes; in my case, they are coming from a dialog wizard 
    LanguageSetupWizard wizard(map_->languages(), true, this); 
    wizard.setWindowModality(Qt::WindowModal); 
    if (QDialog::Accepted == wizard.exec()) { 
#ifdef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY 
    ApplyLanguageChanges(wizard.languages(), wizard.language_renames()); 
#else 
    pending_languages_ = wizard.languages(); 
    pending_language_renames_ = wizard.language_renames(); 
#endif 
    } 
} 

#ifndef YOUR_APP_APPLY_PREFERENCES_IMMEDIATELY 

void PreferencesDialog::ApplyDialog() { 
    if (!pending_languages_.isEmpty()) { 
    ApplyLanguageChanges(pending_languages_, pending_language_renames_); 
    } 
} 

void PreferencesDialog::accept() { 
    ApplyDialog(); 
    QDialog::accept(); 
} 
#endif 
0

QSettings est une abstraction multi-plateforme qui peut être utilisé pour enregistrer les préférences, donc j'espère que cela évite l'utilisation de #IFDEFsJ'ai également constaté qu'il a vraiment de bonnes performances. Tellement bon, en fait, que je viens d'installer un écouteur d'événements et appelé save() sur chaque événement unique.

classe contient un filtre d'événement de la forme comme ceci:

def __init__(self, *args, **kwargs): 
    # .... 
    self.installEventFilter(self) 
    # .... 

def eventFilter(self, obj, event): 
    self.save() 
    return False 

Et ma méthode save() ressemble à ceci:

self.app.settings.setValue(self.state_key, self.header.saveState()) 
self.app.settings.setValue(self.geometry_key, self.header.saveGeometry()) 
self.app.settings.setValue("connect_timeout_spinBox_value", self.connect_timeout_spinBox.value()) 
self.app.settings.setValue("reveal_downloads_checkbox_checked", self.reveal_downloads_checkbox.checkState()) 

Alors, oui, vous avez à faire une jambe-travail vous-même pour obtenir vos prefs sauvés immédiatement - mais je ne l'ai pas trouvé trop pénible.

Et bien qu'il se sente (encore) un peu gêné de pulvériser save() à chaque événement, les bonnes performances ont rendu cette opération indétectable pour l'utilisateur.

Écrire une petite classe qui énumère chaque widget sur un formulaire et enregistre/restaure chacune de ses propriétés dans QSettings serait également soigné. Cela peut être approprié si vous avez quelques dizaines/centaines de préférences. Je posterai ici quand je l'aurai fait.