/* smplayer, GUI front-end for mplayer. Copyright (C) 2007 Ricardo Villalba This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This is based on qq14-actioneditor-code.zip from Qt */ #include "actionseditor.h" #if QT_VERSION < 0x040000 #define USE_KEYCHOOSER 1 #else #define USE_KEYCHOOSER 0 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "images.h" #include "filedialog.h" #include "helper.h" #include "mytable.h" #if USE_KEYCHOOSER #include "keychooser.h" #else #include #endif class ShortcutItem : public QTableItem { public: ShortcutItem( QTable * table, const QString & text ); virtual int alignment () const; virtual QWidget * createEditor () const; }; ShortcutItem::ShortcutItem( QTable * table, const QString & text ) #if USE_KEYCHOOSER : QTableItem(table, QTableItem::WhenCurrent, text) #else : QTableItem(table, QTableItem::OnTyping, text) #endif { } QWidget * ShortcutItem::createEditor () const { #if USE_KEYCHOOSER KeyChooser * key_chooser = new KeyChooser( table()->viewport() ); key_chooser->setText( text() ); return key_chooser; #else QLineEdit * edit = new QLineEdit( table()->viewport() ); edit->setText( text() ); return edit; #endif } int ShortcutItem::alignment() const { //return Qt::AlignHCenter; return Qt::AlignAuto; } #define COL_CONFLICTS 0 #define COL_SHORTCUT 1 #define COL_DESC 2 #define COL_NAME 3 ActionsEditor::ActionsEditor(QWidget * parent, const char * name, WFlags f) : QWidget(parent, name, f) { latest_dir = Helper::shortcutsPath(); actionsTable = new MyTable(0, COL_NAME +1, this); actionsTable->setSizeHint(QSize(100,100)); actionsTable->setColumnReadOnly(COL_NAME, true); actionsTable->setColumnReadOnly(COL_DESC, true); actionsTable->setColumnReadOnly(COL_CONFLICTS, true); actionsTable->setColumnStretchable(COL_NAME, true); actionsTable->setColumnStretchable(COL_DESC, true); actionsTable->verticalHeader()->hide(); actionsTable->setLeftMargin(0); saveButton = new QPushButton(this); loadButton = new QPushButton(this); connect(actionsTable, SIGNAL(currentChanged(int, int)), this, SLOT(recordAction(int, int))); connect(actionsTable, SIGNAL(valueChanged(int, int)), this, SLOT(validateAction(int, int))); connect(saveButton, SIGNAL(clicked()), this, SLOT(saveActionsTable())); connect(loadButton, SIGNAL(clicked()), this, SLOT(loadActionsTable())); QHBoxLayout *buttonLayout = new QHBoxLayout; buttonLayout->setSpacing(8); buttonLayout->addStretch(1); buttonLayout->addWidget(loadButton); buttonLayout->addWidget(saveButton); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->setMargin(8); mainLayout->setSpacing(8); mainLayout->addWidget(actionsTable); mainLayout->addLayout(buttonLayout); languageChange(); } ActionsEditor::~ActionsEditor() { } void ActionsEditor::languageChange() { actionsTable->horizontalHeader()->setLabel(COL_NAME, tr("Name")); actionsTable->horizontalHeader()->setLabel(COL_DESC, tr("Description")); actionsTable->horizontalHeader()->setLabel(COL_SHORTCUT, tr("Shortcut")); actionsTable->horizontalHeader()->setLabel(COL_CONFLICTS, ""); saveButton->setText(tr("&Save")); saveButton->setPixmap(Images::icon("save")); loadButton->setText(tr("&Load")); loadButton->setPixmap(Images::icon("open")); //updateView(); // The actions are translated later, so it's useless } bool ActionsEditor::isEmpty() { return actionsList.isEmpty(); } void ActionsEditor::clear() { actionsList.clear(); } void ActionsEditor::addActions(QWidget *widget) { QACTION *action; #if QT_VERSION < 0x040000 QObjectList *actions = widget->queryList("QAction"); action = static_cast(actions->first()); while (action) { if (!action->inherits("QActionGroup")) actionsList.append(action); action = static_cast(actions->next()); } #else QList actions = widget->findChildren(); for (int n=0; n < actions.count(); n++) { action = static_cast (actions[n]); if (!action->inherits("Q3ActionGroup")) actionsList.append(action); } #endif updateView(); } void ActionsEditor::updateView() { actionsTable->setNumRows( actionsList.count() ); QACTION *action; QString accelText; for (int n=0; n < actionsList.count(); n++) { action = static_cast (actionsList[n]); QPixmap p = action->iconSet().pixmap(); if (!p.isNull()) p = Images::resize(&p, 16); accelText = QString(action->accel()); actionsTable->setPixmap(n, COL_DESC, p ); actionsTable->setText(n, COL_NAME, action->name()); actionsTable->setText(n, COL_DESC, action->text()); //actionsTable->setText(n, COL_SHORTCUT, QString(action->accel())); actionsTable->setItem( n, COL_SHORTCUT, new ShortcutItem(actionsTable, accelText) ); } hasConflicts(); // Check for conflicts actionsTable->adjustColumn( COL_NAME ); actionsTable->adjustColumn( COL_DESC ); actionsTable->adjustColumn( COL_CONFLICTS ); //actionsTable->resizeContents(100,100); } void ActionsEditor::applyChanges() { qDebug("ActionsEditor::applyChanges"); for (int row = 0; row < (int)actionsList.size(); ++row) { QACTION *action = actionsList[row]; action->setAccel(QKeySequence(actionsTable->text(row, COL_SHORTCUT))); } } void ActionsEditor::recordAction(int row, int column) { if (column == COL_SHORTCUT) { oldAccelText = actionsTable->item(row, column)->text(); } } void ActionsEditor::validateAction(int row, int column) { if (column == COL_SHORTCUT) { QTableItem *item = actionsTable->item(row, column); QString accelText = QString(QKeySequence(item->text())); if (accelText.isEmpty() && !item->text().isEmpty()) item->setText(oldAccelText); else item->setText(accelText); if (hasConflicts()) qApp->beep(); } } int ActionsEditor::findActionName(const QString & name) { for (int row=0; row < actionsTable->numRows(); row++) { if (actionsTable->text(row, COL_NAME) == name) return row; } return -1; } int ActionsEditor::findActionAccel(const QString & accel, int ignoreRow) { for (int row=0; row < actionsTable->numRows(); row++) { if (actionsTable->text(row, COL_SHORTCUT) == accel) { if (ignoreRow == -1) return row; else if (ignoreRow != row) return row; } } return -1; } bool ActionsEditor::hasConflicts() { int found; bool conflict = false; QString accelText; for (int n=0; n < actionsTable->numRows(); n++) { //actionsTable->setText( n, COL_CONFLICTS, " "); actionsTable->setPixmap( n, COL_CONFLICTS, QPixmap() ); accelText = actionsTable->text(n, COL_SHORTCUT ); if (!accelText.isEmpty()) { found = findActionAccel( accelText, n ); if ( (found != -1) && (found != n) ) { conflict = true; //actionsTable->setText( n, COL_CONFLICTS, "!"); actionsTable->setPixmap( n, COL_CONFLICTS, Images::icon("conflict")); } } } //if (conflict) qApp->beep(); return conflict; } void ActionsEditor::saveActionsTable() { QString s = MyFileDialog::getSaveFileName( latest_dir, tr("Key files") +" (*.keys)", this, "save file dialog", tr("Choose a filename") ); if (!s.isEmpty()) { // If filename has no extension, add it if (QFileInfo(s).extension().isEmpty()) { s = s + ".keys"; } if (QFileInfo(s).exists()) { int res = QMessageBox::question( this, tr("Confirm overwrite?"), tr("The file %1 already exists.\n" "Do you want to overwrite?").arg(s), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton); if (res == QMessageBox::No ) { return; } } latest_dir = QFileInfo(s).dirPath(TRUE); bool r = saveActionsTable(s); if (!r) { QMessageBox::warning(this, tr("Error"), tr("The file couldn't be saved"), QMessageBox::Ok, QMessageBox::NoButton); } } } bool ActionsEditor::saveActionsTable(const QString & filename) { qDebug("ActionsEditor::saveActions: '%s'", filename.utf8().data()); QFile f( filename ); if ( f.open( IO_WriteOnly ) ) { QTextStream stream( &f ); stream.setEncoding(QTextStream::UnicodeUTF8); for (int row=0; row < actionsTable->numRows(); row++) { stream << actionsTable->text(row, COL_NAME) << "\t" << actionsTable->text(row, COL_SHORTCUT) << "\n"; } f.close(); return true; } return false; } void ActionsEditor::loadActionsTable() { QString s = MyFileDialog::getOpenFileName( latest_dir, tr("Key files") +" (*.keys)", this, "open file dialog", tr("Choose a file") ); if (!s.isEmpty()) { latest_dir = QFileInfo(s).dirPath(TRUE); bool r = loadActionsTable(s); if (!r) { QMessageBox::warning(this, tr("Error"), tr("The file couldn't be loaded"), QMessageBox::Ok, QMessageBox::NoButton); } } } bool ActionsEditor::loadActionsTable(const QString & filename) { qDebug("ActionsEditor::loadActions: '%s'", filename.utf8().data()); QRegExp rx("^(.*)\\t(.*)"); int row; QFile f( filename ); if ( f.open( IO_ReadOnly ) ) { QTextStream stream( &f ); stream.setEncoding(QTextStream::UnicodeUTF8); QString line; while ( !stream.atEnd() ) { line = stream.readLine(); qDebug("line: '%s'", line.utf8().data()); if (rx.search(line) > -1) { QString name = rx.cap(1); QString accelText = rx.cap(2); qDebug(" name: '%s' accel: '%s'", name.utf8().data(), accelText.utf8().data()); row = findActionName(name); if (row > -1) { qDebug("Action found!"); actionsTable->setText(row, COL_SHORTCUT, accelText); } } else { qDebug(" wrong line"); } } f.close(); hasConflicts(); // Check for conflicts return true; } else { return false; } } // Static functions void ActionsEditor::saveToConfig(QObject *o, QSettings *set) { qDebug("ActionsEditor::saveToConfig"); set->beginGroup("actions"); QACTION *action; #if QT_VERSION < 0x040000 QObjectList *actions = o->queryList("QAction"); action = static_cast(actions->first()); while (action) { QString accelText = QString(action->accel()); set->writeEntry(action->name(), accelText); action = static_cast(actions->next()); } #else QList actions = o->findChildren(); for (int n=0; n < actions.count(); n++) { action = static_cast (actions[n]); QString accelText = QString(action->accel()); set->writeEntry(action->name(), accelText); } #endif set->endGroup(); } void ActionsEditor::loadFromConfig(QObject *o, QSettings *set) { qDebug("ActionsEditor::loadFromConfig"); set->beginGroup("actions"); QACTION *action; QString accelText; #if QT_VERSION < 0x040000 QObjectList *actions = o->queryList("QAction"); action = static_cast(actions->first()); while (action) { accelText = set->readEntry(action->name(), action->accel()); action->setAccel(QKeySequence(accelText)); action = static_cast(actions->next()); } #else QList actions = o->findChildren(); for (int n=0; n < actions.count(); n++) { action = static_cast (actions[n]); accelText = set->readEntry(action->name(), action->accel()); action->setAccel(QKeySequence(accelText)); } #endif set->endGroup(); } QACTION * ActionsEditor::findAction(QObject *o, const QString & name) { QACTION *action; #if QT_VERSION < 0x040000 QObjectList *actions = o->queryList("QAction"); action = static_cast(actions->first()); while (action) { if (name == action->name()) return action; action = static_cast(actions->next()); } #else QList actions = o->findChildren(); for (int n=0; n < actions.count(); n++) { action = static_cast (actions[n]); if (name == action->objectName()) return action; } #endif return 0; } QStringList ActionsEditor::actionsNames(QObject *o) { QStringList l; QACTION *action; #if QT_VERSION < 0x040000 QObjectList *actions = o->queryList("QAction"); action = static_cast(actions->first()); while (action) { l.append( action->name() ); action = static_cast(actions->next()); } #else QList actions = o->findChildren(); for (int n=0; n < actions.count(); n++) { action = static_cast (actions[n]); l.append( action->name() ); } #endif return l; }