/* Copyright 2007-2008 by Robert Knight 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ // Own #include "ManageProfilesDialog.h" // Qt #include #include #include #include #include #include #include #include // KDE #include #include // Konsole #include "EditProfileDialog.h" #include "SessionManager.h" #include "ui_ManageProfilesDialog.h" using namespace Konsole; ManageProfilesDialog::ManageProfilesDialog(QWidget* parent) : KDialog(parent) { setCaption(i18n("Manage Profiles")); setButtons( KDialog::Close ); _ui = new Ui::ManageProfilesDialog(); _ui->setupUi(mainWidget()); // hide vertical header _ui->sessionTable->verticalHeader()->hide(); _ui->sessionTable->setItemDelegateForColumn(FavoriteStatusColumn,new FavoriteItemDelegate(this)); _ui->sessionTable->setItemDelegateForColumn(ShortcutColumn,new ShortcutItemDelegate(this)); _ui->sessionTable->setEditTriggers(_ui->sessionTable->editTriggers() | QAbstractItemView::SelectedClicked); // update table and listen for changes to the session types updateTableModel(); connect( SessionManager::instance() , SIGNAL(profileAdded(Profile::Ptr)) , this, SLOT(updateTableModel()) ); connect( SessionManager::instance() , SIGNAL(profileRemoved(Profile::Ptr)) , this, SLOT(updateTableModel()) ); connect( SessionManager::instance() , SIGNAL(profileChanged(Profile::Ptr)) , this, SLOT(updateTableModel()) ); connect( SessionManager::instance() , SIGNAL(favoriteStatusChanged(Profile::Ptr,bool)) , this , SLOT(updateFavoriteStatus(Profile::Ptr,bool)) ); // resize the session table to the full width of the table _ui->sessionTable->horizontalHeader()->setHighlightSections(false); _ui->sessionTable->resizeColumnsToContents(); // allow a larger width for the shortcut column to account for the // increased with needed by the shortcut editor compared with just // displaying the text of the shortcut _ui->sessionTable->setColumnWidth(ShortcutColumn, _ui->sessionTable->columnWidth(ShortcutColumn)+100); // setup buttons connect( _ui->newSessionButton , SIGNAL(clicked()) , this , SLOT(newType()) ); connect( _ui->editSessionButton , SIGNAL(clicked()) , this , SLOT(editSelected()) ); connect( _ui->deleteSessionButton , SIGNAL(clicked()) , this , SLOT(deleteSelected()) ); connect( _ui->setAsDefaultButton , SIGNAL(clicked()) , this , SLOT(setSelectedAsDefault()) ); } void ManageProfilesDialog::showEvent(QShowEvent*) { Q_ASSERT( _ui->sessionTable->model() ); // try to ensure that all the text in all the columns is visible initially. // FIXME: this is not a good solution, look for a more correct way to do this int totalWidth = 0; int columnCount = _ui->sessionTable->model()->columnCount(); for ( int i = 0 ; i < columnCount ; i++ ) totalWidth += _ui->sessionTable->columnWidth(i); // the margin is added to account for the space taken by the resize grips // between the columns, this ensures that a horizontal scroll bar is not added // automatically int margin = style()->pixelMetric( QStyle::PM_HeaderGripMargin ) * columnCount; _ui->sessionTable->setMinimumWidth( totalWidth + margin ); _ui->sessionTable->horizontalHeader()->setStretchLastSection(true); } ManageProfilesDialog::~ManageProfilesDialog() { delete _ui; } void ManageProfilesDialog::itemDataChanged(QStandardItem* item) { if ( item->column() == ShortcutColumn ) { QKeySequence sequence = QKeySequence::fromString(item->text()); kDebug() << "New key sequence: " << item->text(); SessionManager::instance()->setShortcut(item->data(ShortcutRole).value(), sequence); } } void ManageProfilesDialog::updateTableModel() { // ensure profiles list is complete // this may be EXPENSIVE, but will only be done the first time // that the dialog is shown. SessionManager::instance()->loadAllProfiles(); // setup session table _sessionModel = new QStandardItemModel(this); _sessionModel->setHorizontalHeaderLabels( QStringList() << i18n("Name") << i18n("Show in Menu") << i18n("Shortcut") ); QListIterator profileIter( SessionManager::instance()->loadedProfiles() ); while ( profileIter.hasNext() ) { Profile::Ptr info = profileIter.next(); if ( info->isHidden() ) continue; QList itemList; QStandardItem* item = new QStandardItem( info->name() ); if ( !info->icon().isEmpty() ) item->setIcon( KIcon(info->icon()) ); item->setData(QVariant::fromValue(info),ProfileKeyRole); const bool isFavorite = SessionManager::instance()->findFavorites().contains(info); // favorite column QStandardItem* favoriteItem = new QStandardItem(); if ( isFavorite ) favoriteItem->setData(KIcon("favorites"),Qt::DecorationRole); else favoriteItem->setData(KIcon(),Qt::DecorationRole); favoriteItem->setData(QVariant::fromValue(info),ProfileKeyRole); // shortcut column QStandardItem* shortcutItem = new QStandardItem(); QString shortcut = SessionManager::instance()->shortcut(info). toString(); shortcutItem->setText(shortcut); shortcutItem->setData(QVariant::fromValue(info),ShortcutRole); itemList << item << favoriteItem << shortcutItem; _sessionModel->appendRow(itemList); } updateDefaultItem(); connect( _sessionModel , SIGNAL(itemChanged(QStandardItem*)) , this , SLOT(itemDataChanged(QStandardItem*)) ); _ui->sessionTable->setModel(_sessionModel); // listen for changes in the table selection and update the state of the form's buttons // accordingly. // // it appears that the selection model is changed when the model itself is replaced, // so the signals need to be reconnected each time the model is updated. // // the view ( _ui->sessionTable ) has a selectionChanged() signal which it would be // preferable to connect to instead of the one belonging to the view's current // selection model, but QAbstractItemView::selectionChanged() is protected // connect( _ui->sessionTable->selectionModel() , SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)) , this , SLOT(tableSelectionChanged(const QItemSelection&)) ); tableSelectionChanged( _ui->sessionTable->selectionModel()->selection() ); } void ManageProfilesDialog::updateDefaultItem() { Profile::Ptr defaultProfile = SessionManager::instance()->defaultProfile(); for ( int i = 0 ; i < _sessionModel->rowCount() ; i++ ) { QStandardItem* item = _sessionModel->item(i); QFont font = item->font(); bool isDefault = ( defaultProfile == item->data().value() ); if ( isDefault && !font.bold() ) { font.setBold(true); item->setFont(font); } else if ( !isDefault && font.bold() ) { font.setBold(false); item->setFont(font); } } } void ManageProfilesDialog::tableSelectionChanged(const QItemSelection& selection) { bool enable = !selection.indexes().isEmpty(); const SessionManager* manager = SessionManager::instance(); const bool isNotDefault = enable && selectedKey() != manager->defaultProfile(); _ui->editSessionButton->setEnabled(enable); // do not allow the default session type to be removed _ui->deleteSessionButton->setEnabled(isNotDefault); _ui->setAsDefaultButton->setEnabled(isNotDefault); } void ManageProfilesDialog::deleteSelected() { // TODO - Possibly add a warning here if the selected profile is the parent of // one or more other profiles since deleting a profile will change the settings // of the profiles which inherit from it. Q_ASSERT( selectedKey() ); Q_ASSERT( selectedKey() != SessionManager::instance()->defaultProfile() ); SessionManager::instance()->deleteProfile(selectedKey()); } void ManageProfilesDialog::setSelectedAsDefault() { SessionManager::instance()->setDefaultProfile(selectedKey()); // do not allow the new default session type to be removed _ui->deleteSessionButton->setEnabled(false); _ui->setAsDefaultButton->setEnabled(false); // update font of new default item updateDefaultItem(); } void ManageProfilesDialog::newType() { EditProfileDialog dialog(this); // setup a temporary profile, inheriting from the selected profile // or the default if no profile is selected Profile::Ptr parentProfile; Profile::Ptr selectedProfile = selectedKey(); if ( !selectedProfile ) parentProfile = SessionManager::instance()->defaultProfile(); else parentProfile = selectedProfile; Q_ASSERT( parentProfile ); Profile::Ptr newProfile = Profile::Ptr(new Profile(parentProfile)); newProfile->setProperty(Profile::Name,i18n("New Profile")); dialog.setProfile(newProfile); dialog.selectProfileName(); if ( dialog.exec() == QDialog::Accepted ) { SessionManager::instance()->addProfile(newProfile); SessionManager::instance()->setFavorite(newProfile,true); } } void ManageProfilesDialog::editSelected() { Q_ASSERT( selectedKey() ); EditProfileDialog dialog(this); dialog.setProfile(selectedKey()); dialog.exec(); } Profile::Ptr ManageProfilesDialog::selectedKey() const { QItemSelectionModel* selection = _ui->sessionTable->selectionModel(); if ( !selection || selection->selectedRows().count() != 1 ) return Profile::Ptr(); // TODO There has to be an easier way of getting the data // associated with the currently selected item return selection-> selectedIndexes().first().data( Qt::UserRole + 1 ).value(); } void ManageProfilesDialog::updateFavoriteStatus(Profile::Ptr profile, bool favorite) { Q_ASSERT( _sessionModel ); int rowCount = _sessionModel->rowCount(); for (int i=0;i < rowCount;i++) { QModelIndex index = _sessionModel->index(i,FavoriteStatusColumn); if (index.data(ProfileKeyRole).value() == profile ) { const KIcon icon = favorite ? KIcon("favorites") : KIcon(); _sessionModel->setData(index,icon,Qt::DecorationRole); } } } void ManageProfilesDialog::setShortcutEditorVisible(bool visible) { _ui->sessionTable->setColumnHidden(ShortcutColumn,!visible); } void StyledBackgroundPainter::drawBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex&) { const QStyleOptionViewItemV3* v3option = qstyleoption_cast(&option); const QWidget* widget = v3option ? v3option->widget : 0; QStyle* style = widget ? widget->style() : QApplication::style(); style->drawPrimitive(QStyle::PE_PanelItemViewItem,&option,painter,widget); } FavoriteItemDelegate::FavoriteItemDelegate(QObject* parent) : QStyledItemDelegate(parent) { } void FavoriteItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { // See implementation of QStyledItemDelegate::paint() QStyleOptionViewItemV4 opt = option; initStyleOption(&opt,index); StyledBackgroundPainter::drawBackground(painter,opt,index); int margin = (opt.rect.height()-opt.decorationSize.height())/2; margin++; opt.rect.setTop(opt.rect.top()+margin); opt.rect.setBottom(opt.rect.bottom()-margin); QIcon icon = index.data(Qt::DecorationRole).value(); icon.paint(painter,opt.rect,Qt::AlignCenter); } bool FavoriteItemDelegate::editorEvent(QEvent* event,QAbstractItemModel*, const QStyleOptionViewItem&,const QModelIndex& index) { if ( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::KeyPress || event->type() == QEvent::MouseButtonDblClick ) { Profile::Ptr profile = index.data(ManageProfilesDialog::ProfileKeyRole).value(); const bool isFavorite = !SessionManager::instance()->findFavorites().contains(profile); SessionManager::instance()->setFavorite(profile, isFavorite); } return true; } ShortcutItemDelegate::ShortcutItemDelegate(QObject* parent) : QStyledItemDelegate(parent) { } void ShortcutItemDelegate::editorModified(const QKeySequence& keys) { kDebug() << keys.toString(); KKeySequenceWidget* editor = qobject_cast(sender()); Q_ASSERT(editor); _modifiedEditors.insert(editor); } void ShortcutItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const { _itemsBeingEdited.remove(index); if (!_modifiedEditors.contains(editor)) return; QString shortcut = qobject_cast(editor)->keySequence().toString(); model->setData(index,shortcut,Qt::DisplayRole); _modifiedEditors.remove(editor); } QWidget* ShortcutItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem&, const QModelIndex& index) const { _itemsBeingEdited.insert(index); KKeySequenceWidget* editor = new KKeySequenceWidget(parent); editor->setFocusPolicy(Qt::StrongFocus); editor->setModifierlessAllowed(false); QString shortcutString = index.data(Qt::DisplayRole).toString(); editor->setKeySequence(QKeySequence::fromString(shortcutString)); connect(editor,SIGNAL(keySequenceChanged(QKeySequence)),this,SLOT(editorModified(QKeySequence))); editor->captureKeySequence(); return editor; } void ShortcutItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const { if (_itemsBeingEdited.contains(index)) StyledBackgroundPainter::drawBackground(painter,option,index); else QStyledItemDelegate::paint(painter,option,index); } #include "ManageProfilesDialog.moc"