Work on skins.

This commit is contained in:
Martin Rotter 2013-09-20 18:18:49 +02:00
parent 99c011de41
commit d995782668
10 changed files with 238 additions and 32 deletions

View file

@ -72,6 +72,13 @@
<translation>Hypertextový odkaz</translation>
</message>
</context>
<context>
<name>CornerButton</name>
<message>
<source>Open new tab</source>
<translation>Otevřít nový panel</translation>
</message>
</context>
<context>
<name>FormAbout</name>
<message>
@ -210,7 +217,7 @@
</message>
<message>
<source>Language</source>
<translation>Lokalizacce</translation>
<translation>Lokalizace</translation>
</message>
<message>
<source>Proxy</source>
@ -424,6 +431,15 @@
<source>no icon theme</source>
<translation>žádné téma ikon</translation>
</message>
<message>
<source>Some keyboard shortcuts are not unique.
</source>
<translation>Některé klávesové zkrátky jsou duplicitní.</translation>
</message>
<message>
<source>Cannot save settings</source>
<translation>Nastavení nelze uložit</translation>
</message>
</context>
<context>
<name>FormWelcome</name>
@ -468,6 +484,13 @@
<translation>rotter.martinos@gmail.com</translation>
</message>
</context>
<context>
<name>SkinFactory</name>
<message>
<source>default system skin</source>
<translation>výchozí systémový vzhled</translation>
</message>
</context>
<context>
<name>TabWidget</name>
<message>

View file

@ -72,6 +72,13 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>CornerButton</name>
<message>
<source>Open new tab</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormAbout</name>
<message>
@ -418,6 +425,15 @@
<source>no icon theme</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Some keyboard shortcuts are not unique.
</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Cannot save settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FormWelcome</name>
@ -462,6 +478,13 @@
<translation>rotter.martinos@gmail.com</translation>
</message>
</context>
<context>
<name>SkinFactory</name>
<message>
<source>default system skin</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>TabWidget</name>
<message>

View file

@ -19,6 +19,25 @@ DynamicShortcutsWidget::~DynamicShortcutsWidget() {
delete m_layout;
}
bool DynamicShortcutsWidget::areShortcutsUnique() {
QList<QKeySequence> all_shortcuts;
// Obtain all shortcuts.
foreach (ActionBinding binding, m_actionBindings) {
QKeySequence new_shortcut = binding.second->shortcut();
if (all_shortcuts.contains(new_shortcut)) {
// Problem, two identical shortcuts found.
return false;
}
else {
all_shortcuts.append(binding.second->shortcut());
}
}
return true;
}
void DynamicShortcutsWidget::updateShortcuts() {
foreach (ActionBinding binding, m_actionBindings) {
binding.first->setShortcut(binding.second->shortcut());

View file

@ -23,6 +23,10 @@ class DynamicShortcutsWidget : public QWidget {
// and stored back to settings when application quits.
void updateShortcuts();
// Returns true if all shortcuts are unique,
// otherwise false.
bool areShortcutsUnique();
// Populates this widget with shortcut widgets for given actions.
// NOTE: This gets initial shortcut for each action from its properties, NOT from
// the application settings, so shortcuts from settings need to be

View file

@ -5,6 +5,7 @@
#include "gui/formsettings.h"
#include "gui/iconthemefactory.h"
#include "gui/skinfactory.h"
#include "gui/systemtrayicon.h"
#include "gui/formmain.h"
#include "gui/webbrowser.h"
@ -28,17 +29,31 @@ FormSettings::FormSettings(QWidget *parent) : QDialog(parent), m_ui(new Ui::Form
m_ui->m_treeLanguages->setHeaderHidden(false);
#if QT_VERSION >= 0x050000
// Setup languages.
m_ui->m_treeLanguages->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setSectionResizeMode(4, QHeaderView::ResizeToContents);
// Setup skins.
m_ui->m_treeSkins->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(2, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
#else
// Setup languages.
m_ui->m_treeLanguages->header()->setResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setResizeMode(2, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setResizeMode(3, QHeaderView::ResizeToContents);
m_ui->m_treeLanguages->header()->setResizeMode(4, QHeaderView::ResizeToContents);
// Setup skins.
m_ui->m_treeSkins->header()->setResizeMode(0, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setResizeMode(1, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setResizeMode(2, QHeaderView::ResizeToContents);
m_ui->m_treeSkins->header()->setResizeMode(3, QHeaderView::ResizeToContents);
#endif
m_ui->m_treeLanguages->setHeaderLabels(QStringList()
@ -48,8 +63,15 @@ FormSettings::FormSettings(QWidget *parent) : QDialog(parent), m_ui(new Ui::Form
<< tr("Author")
<< tr("Email"));
m_ui->m_treeSkins->setHeaderLabels(QStringList()
<< tr("Name")
<< tr("Version")
<< tr("Author")
<< tr("Email"));
// Establish needed connections.
connect(this, SIGNAL(accepted()), this, SLOT(saveSettings()));
connect(m_ui->m_buttonBox, SIGNAL(accepted()),
this, SLOT(saveSettings()));
connect(m_ui->m_cmbProxyType, SIGNAL(currentIndexChanged(int)),
this, SLOT(onProxyTypeChanged(int)));
connect(m_ui->m_checkShowPassword, SIGNAL(stateChanged(int)),
@ -88,7 +110,31 @@ void FormSettings::displayProxyPassword(int state) {
}
}
bool FormSettings::doSaveCheck() {
bool everything_ok = true;
QString resulting_information;
everything_ok &= m_ui->m_shortcuts->areShortcutsUnique();
if (!m_ui->m_shortcuts->areShortcutsUnique()) {
resulting_information = resulting_information.append(tr("Some keyboard shortcuts are not unique.\n"));
}
if (!everything_ok) {
QMessageBox::warning(this,
tr("Cannot save settings"),
resulting_information);
}
return everything_ok;
}
void FormSettings::saveSettings() {
// Make sure everything is saveable.
if (!doSaveCheck()) {
return;
}
// Save all settings.
saveGeneral();
saveShortcuts();
@ -98,6 +144,8 @@ void FormSettings::saveSettings() {
saveLanguage();
Settings::getInstance()->checkSettings();
accept();
}
void FormSettings::onProxyTypeChanged(int index) {
@ -349,6 +397,26 @@ void FormSettings::loadInterface() {
m_ui->m_cmbIconTheme->setCurrentIndex(theme_index);
}
#endif
// Load skin.
QList<Skin> installed_skins = SkinFactory::getInstance()->getInstalledSkins();
QString active_skin = SkinFactory::getInstance()->getCurrentSkinName();
foreach (Skin skin, installed_skins) {
QTreeWidgetItem *new_item = new QTreeWidgetItem(QStringList() <<
skin.m_visibleName <<
skin.m_version <<
skin.m_author <<
skin.m_email);
new_item->setData(0, Qt::UserRole, QVariant::fromValue(skin));
// Add this skin and mark it as active if its active now.
m_ui->m_treeSkins->addTopLevelItem(new_item);
if (skin.m_baseName == active_skin) {
m_ui->m_treeSkins->setCurrentItem(new_item);
}
}
}
// Load tab settings.
@ -387,6 +455,10 @@ void FormSettings::saveInterface() {
QString selected_icon_theme = m_ui->m_cmbIconTheme->itemData(m_ui->m_cmbIconTheme->currentIndex()).toString();
IconThemeFactory::getInstance()->setCurrentIconTheme(selected_icon_theme);
// Save and activate new skin.
Skin active_skin = m_ui->m_treeSkins->currentItem()->data(0, Qt::UserRole).value<Skin>();
SkinFactory::getInstance()->setCurrentSkinName(active_skin.m_baseName);
// Save tab settings.
settings->setValue(APP_CFG_GUI, "tab_close_mid_button",
m_ui->m_checkCloseTabsMiddleClick->isChecked());

View file

@ -22,6 +22,9 @@ class FormSettings : public QDialog {
explicit FormSettings(QWidget *parent = 0);
virtual ~FormSettings();
protected:
bool doSaveCheck();
protected slots:
// Saves settings into global configuration.
void saveSettings();

View file

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>680</width>
<width>829</width>
<height>414</height>
</rect>
</property>
@ -17,7 +17,7 @@
<item row="0" column="1">
<widget class="QStackedWidget" name="m_stackedSettings">
<property name="currentIndex">
<number>4</number>
<number>2</number>
</property>
<widget class="QWidget" name="m_pageGeneral">
<layout class="QFormLayout" name="formLayout_5">
@ -69,8 +69,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>100</width>
<height>30</height>
<width>585</width>
<height>368</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
@ -142,8 +142,29 @@
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="m_cmbSkin"/>
<item row="2" column="0" colspan="2">
<widget class="QTreeWidget" name="m_treeSkins">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="indentation">
<number>0</number>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
@ -528,9 +549,15 @@
</item>
<item row="0" column="0">
<widget class="QListWidget" name="m_listSettings">
<property name="minimumSize">
<size>
<width>220</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<width>220</width>
<height>16777215</height>
</size>
</property>
@ -586,22 +613,6 @@
</customwidgets>
<resources/>
<connections>
<connection>
<sender>m_buttonBox</sender>
<signal>accepted()</signal>
<receiver>FormSettings</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>404</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>m_buttonBox</sender>
<signal>rejected()</signal>

View file

@ -34,10 +34,15 @@ void SkinFactory::loadCurrentSkin() {
bool loaded = false;
Skin skin_data = getSkinInfo(skin_name_from_settings, &loaded);
if (loaded) {
if (skin_name_from_settings == APP_THEME_SYSTEM) {
qApp->setStyleSheet(QString());
qApp->setStyle(NULL);
qDebug("System default skin loaded.");
}
else if (loaded) {
loadSkinFromData(skin_data.m_rawData, skin_name_from_settings);
foreach (QString style, skin_data.m_stylesName.split("\n")) {
foreach (QString style, skin_data.m_stylesNames) {
if (qApp->setStyle(style) != 0) {
qDebug("Style '%s' loaded.", qPrintable(style));
break;
@ -103,14 +108,20 @@ Skin SkinFactory::getSkinInfo(const QString &skin_name, bool *ok) {
return skin;
}
// Obtain visible skin name.
query.setQuery("string(skin/name)");
query.evaluateTo(&skin.m_visibleName);
skin.m_visibleName = skin.m_visibleName.remove("\n");
// Obtain skin raw data.
query.setQuery("string(skin/data)");
query.evaluateTo(&skin.m_rawData);
// Obtain style name.
query.setQuery("string(/skin/style)");
query.evaluateTo(&skin.m_stylesName);
skin.m_stylesName = skin.m_stylesName.remove("\n");
QString styles;
query.evaluateTo(&styles);
skin.m_stylesNames = styles.remove("\n").split(",");
// Obtain author.
query.setQuery("string(/skin/author/name)");
@ -137,7 +148,7 @@ Skin SkinFactory::getSkinInfo(const QString &skin_name, bool *ok) {
if (ok) {
*ok = !skin.m_author.isEmpty() && !skin.m_version.isEmpty() &&
!skin.m_baseName.isEmpty() && !skin.m_email.isEmpty() &&
!skin.m_rawData.isEmpty() && !skin.m_stylesName.isEmpty();
!skin.m_rawData.isEmpty() && !skin.m_stylesNames.isEmpty();
}
return skin;
@ -145,5 +156,36 @@ Skin SkinFactory::getSkinInfo(const QString &skin_name, bool *ok) {
QList<Skin> SkinFactory::getInstalledSkins() {
QList<Skin> skins;
Skin default_skin;
default_skin.m_author = "-";
default_skin.m_baseName = APP_THEME_SYSTEM;
default_skin.m_email = "-";
default_skin.m_version = "-";
default_skin.m_visibleName = tr("default system skin");
skins.append(default_skin);
bool skin_load_ok;
QStringList skin_directories = QDir(APP_SKIN_PATH).entryList(QDir::Dirs |
QDir::NoDotAndDotDot |
QDir::NoSymLinks |
QDir::Readable);
foreach (QString base_directory, skin_directories) {
// Check skins installed in this base directory.
QStringList skin_files = QDir(APP_SKIN_PATH + QDir::separator() + base_directory).entryList(QStringList() << "*.xml",
QDir::Files | QDir::Readable | QDir::NoDotAndDotDot | QDir::NoSymLinks);
foreach (QString skin_file, skin_files) {
// Check if skin file is valid and add it if it is valid.
Skin skin_info = getSkinInfo(base_directory + QDir::separator() + skin_file,
&skin_load_ok);
if (skin_load_ok) {
skins.append(skin_info);
}
}
}
return skins;
}

View file

@ -3,23 +3,31 @@
#include <QObject>
#include <QPointer>
#include <QStringList>
#include <QMetaType>
struct Skin {
QString m_baseName;
QString m_stylesName;
QString m_visibleName;
QStringList m_stylesNames;
QString m_author;
QString m_email;
QString m_version;
QString m_rawData;
};
Q_DECLARE_METATYPE(Skin)
class SkinFactory : public QObject {
Q_OBJECT
private:
explicit SkinFactory(QObject *parent = 0);
// Loads the skin from give skin_data.
// NOTE: Extra relative path escaping is done for loading of
// external resources.
bool loadSkinFromData(QString skin_data, const QString &skin_path);
public:

View file

@ -72,6 +72,7 @@ int main(int argc, char *argv[]) {
IconThemeFactory::getInstance()->setupSearchPaths();
IconThemeFactory::getInstance()->loadCurrentIconTheme(false);
SkinFactory::getInstance()->loadCurrentSkin();
SkinFactory::getInstance()->getInstalledSkins();
// Load localization and setup locale before any widget is constructed.
LoadLocalization();