From 37088799cfdaf84740575bbf7e32114bdfcc0ccd Mon Sep 17 00:00:00 2001 From: Robert Knight Date: Thu, 5 Jul 2007 09:51:06 +0000 Subject: [PATCH] * Update the regular expression for the Url filter. Anything in the form letters://any-non-whitespace-characters is treated as a Url * Correct the test which compares the old and new values and ranges when updating the terminal display's scroll bar. This fixes the scroll bar being repainted unnecessarily often. Found with the nifty QT_FLUSH_PAINT debugging tool. * Select the profile name (set to "New Profile" by default) and focus the profile name edit area when showing the Edit Profile dialog for a new profile to allow the user to easily set the name. * Always use color scheme list animation, not just when the Edit Profile dialog is first displayed as per richmoore's suggestion. * Update Edit Profile dialog caption when profile name is changed. * Update favorite status icon in Manage Profiles dialog when the favorite status is changed by another object. * Add disabled menu item which is shown in the 'Change Profile' list when there are no other profiles there svn path=/trunk/KDE/kdebase/apps/konsole/; revision=683787 --- src/EditProfileDialog.cpp | 36 ++++++++++++++++++++----------- src/EditProfileDialog.h | 14 +++++++++++- src/Filter.cpp | 2 +- src/ManageProfilesDialog.cpp | 42 +++++++++++++++++++++++++----------- src/ManageProfilesDialog.h | 9 ++++++++ src/ProcessInfo.cpp | 9 ++++++++ src/ProcessInfo.h | 9 ++++++++ src/ProfileList.cpp | 21 ++++++++++++++++++ src/ProfileList.h | 4 ++++ src/TerminalDisplay.cpp | 4 ++-- 10 files changed, 122 insertions(+), 28 deletions(-) diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp index 3795ed302..79be903cb 100644 --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -57,6 +57,7 @@ using namespace Konsole; EditProfileDialog::EditProfileDialog(QWidget* parent) : KDialog(parent) + , _colorSchemeAnimationTimeLine(0) { setCaption(i18n("Edit Profile")); setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply | KDialog::Default ); @@ -78,7 +79,7 @@ EditProfileDialog::EditProfileDialog(QWidget* parent) // to be refreshed when the user switches to them _pageNeedsUpdate.resize( _ui->tabWidget->count() ); connect( _ui->tabWidget , SIGNAL(currentChanged(int)) , this , - SLOT(ensurePageLoaded(int)) ); + SLOT(preparePage(int)) ); _tempProfile = new Profile; @@ -116,6 +117,10 @@ void EditProfileDialog::accept() unpreviewAll(); KDialog::accept(); } +void EditProfileDialog::updateCaption(const QString& profileName) +{ + setCaption( i18n("Edit Profile \"%1\"",profileName) ); +} void EditProfileDialog::setProfile(const QString& key) { _profileKey = key; @@ -125,14 +130,14 @@ void EditProfileDialog::setProfile(const QString& key) Q_ASSERT( info ); // update caption - setCaption( i18n("Edit Profile \"%1\"",info->name()) ); + updateCaption(info->name()); // mark each page of the dialog as out of date // and force an update of the currently visible page // // the other pages will be updated as necessary _pageNeedsUpdate.fill(true); - ensurePageLoaded( _ui->tabWidget->currentIndex() ); + preparePage( _ui->tabWidget->currentIndex() ); if ( _tempProfile ) { @@ -144,17 +149,17 @@ const Profile* EditProfileDialog::lookupProfile() const { return SessionManager::instance()->profile(_profileKey); } -void EditProfileDialog::ensurePageLoaded(int page) +void EditProfileDialog::preparePage(int page) { const Profile* info = lookupProfile(); Q_ASSERT( _pageNeedsUpdate.count() > page ); Q_ASSERT( info ); + QWidget* pageWidget = _ui->tabWidget->widget(page); + if ( _pageNeedsUpdate[page] ) { - QWidget* pageWidget = _ui->tabWidget->widget(page); - if ( pageWidget == _ui->generalTab ) setupGeneralPage(info); else if ( pageWidget == _ui->tabsTab ) @@ -172,6 +177,15 @@ void EditProfileDialog::ensurePageLoaded(int page) _pageNeedsUpdate[page] = false; } + + // start page entry animation for color schemes + if ( pageWidget == _ui->appearanceTab ) + _colorSchemeAnimationTimeLine->start(); +} +void EditProfileDialog::selectProfileName() +{ + _ui->profileNameEdit->selectAll(); + _ui->profileNameEdit->setFocus(); } void EditProfileDialog::setupGeneralPage(const Profile* info) { @@ -324,6 +338,7 @@ void EditProfileDialog::selectIcon() void EditProfileDialog::profileNameChanged(const QString& text) { _tempProfile->setProperty(Profile::Name,text); + updateCaption(_tempProfile->name()); } void EditProfileDialog::initialDirChanged(const QString& dir) { @@ -354,10 +369,10 @@ void EditProfileDialog::setupAppearancePage(const Profile* info) ColorSchemeViewDelegate* delegate = new ColorSchemeViewDelegate(this); - QTimeLine* timeLine = new QTimeLine( 500 , this ); - delegate->setEntryTimeLine(timeLine); + _colorSchemeAnimationTimeLine = new QTimeLine( 500 , this ); + delegate->setEntryTimeLine(_colorSchemeAnimationTimeLine); - connect( timeLine , SIGNAL(valueChanged(qreal)) , this , + connect( _colorSchemeAnimationTimeLine , SIGNAL(valueChanged(qreal)) , this , SLOT(colorSchemeAnimationUpdate()) ); _ui->colorSchemeList->setItemDelegate(delegate); @@ -387,9 +402,6 @@ void EditProfileDialog::setupAppearancePage(const Profile* info) SLOT(setFontSize(int)) ); connect( _ui->editFontButton , SIGNAL(clicked()) , this , SLOT(showFontDialog()) ); - - // start entry animation - timeLine->start(); } void EditProfileDialog::colorSchemeAnimationUpdate() { diff --git a/src/EditProfileDialog.h b/src/EditProfileDialog.h index 4874b86fb..409f58830 100644 --- a/src/EditProfileDialog.h +++ b/src/EditProfileDialog.h @@ -79,6 +79,14 @@ public: */ void setProfile(const QString& key); + /** + * Selects the text in the profile name edit area. + * When the dialog is being used to create a new profile, + * this can be used to draw the user's attention to the profile name + * and make it easy for them to change it. + */ + void selectProfileName(); + public slots: // reimplemented virtual void accept(); @@ -90,7 +98,7 @@ protected: private slots: // sets up the specified tab page if necessary - void ensurePageLoaded(int); + void preparePage(int); // saves changes to profile void save(); @@ -178,6 +186,8 @@ private: void unpreview(int property); void unpreviewAll(); + void updateCaption(const QString& profileName); + struct RadioOption { QAbstractButton* button; @@ -205,6 +215,8 @@ private: // after an update by a call to ensurePageLoaded() QVector _pageNeedsUpdate; QHash _previewedProperties; + + QTimeLine* _colorSchemeAnimationTimeLine; }; /** diff --git a/src/Filter.cpp b/src/Filter.cpp index 15f5d5634..39bbea0f5 100644 --- a/src/Filter.cpp +++ b/src/Filter.cpp @@ -488,7 +488,7 @@ void UrlFilter::HotSpot::activate(QObject* object) //regexp matches: // full url: // protocolname:// or www. followed by numbers, letters dots and dashes or the '@' character. -const QRegExp UrlFilter::FullUrlRegExp("([a-z]+://|www\\.)[a-zA-Z0-9@\\-\\./]+"); +const QRegExp UrlFilter::FullUrlRegExp("([a-z]+://|www\\.)[^\\s]+"); // email address: // [word chars, dots or dashes]@[word chars, dots or dashes].[word chars] const QRegExp UrlFilter::EmailAddressRegExp("(\\w|\\.|-)+@(\\w|\\.|-)+\\.\\w+"); diff --git a/src/ManageProfilesDialog.cpp b/src/ManageProfilesDialog.cpp index a812017ae..ebc011c71 100644 --- a/src/ManageProfilesDialog.cpp +++ b/src/ManageProfilesDialog.cpp @@ -47,7 +47,7 @@ ManageProfilesDialog::ManageProfilesDialog(QWidget* parent) // hide vertical header _ui->sessionTable->verticalHeader()->hide(); - _ui->sessionTable->setItemDelegateForColumn(1,new ProfileItemDelegate(this)); + _ui->sessionTable->setItemDelegateForColumn(FavoriteStatusColumn,new ProfileItemDelegate(this)); // update table and listen for changes to the session types updateTableModel(); @@ -57,6 +57,9 @@ ManageProfilesDialog::ManageProfilesDialog(QWidget* parent) SLOT(updateTableModel()) ); connect( SessionManager::instance() , SIGNAL(profileChanged(const QString&)) , this, SLOT(updateTableModel()) ); + connect( SessionManager::instance() , + SIGNAL(favoriteStatusChanged(const QString&,bool)) , this , + SLOT(updateFavoriteStatus(const QString&,bool)) ); // resize the session table to the full width of the table _ui->sessionTable->horizontalHeader()->setHighlightSections(false); @@ -106,7 +109,7 @@ void ManageProfilesDialog::itemDataChanged(QStandardItem* item) qDebug() << "New key sequence: " << item->text(); - SessionManager::instance()->setShortcut(item->data(Qt::UserRole+1).value(), + SessionManager::instance()->setShortcut(item->data(ShortcutRole).value(), sequence); } } @@ -137,7 +140,7 @@ void ManageProfilesDialog::updateTableModel() if ( !info->icon().isEmpty() ) item->setIcon( KIcon(info->icon()) ); - item->setData(key); + item->setData(key,ProfileKeyRole); const bool isFavorite = SessionManager::instance()->findFavorites().contains(key); @@ -148,14 +151,14 @@ void ManageProfilesDialog::updateTableModel() else favoriteItem->setData(KIcon(),Qt::DecorationRole); - favoriteItem->setData(key,Qt::UserRole+1); + favoriteItem->setData(key,ProfileKeyRole); // shortcut column QStandardItem* shortcutItem = new QStandardItem(); QString shortcut = SessionManager::instance()->shortcut(key). toString(); shortcutItem->setText(shortcut); - shortcutItem->setData(key,Qt::UserRole+1); + shortcutItem->setData(key,ShortcutRole); itemList << item << favoriteItem << shortcutItem; @@ -246,11 +249,16 @@ void ManageProfilesDialog::newType() newProfile->setProperty(Profile::Name,i18n("New Profile")); const QString& key = SessionManager::instance()->addProfile(newProfile); dialog.setProfile(key); - + dialog.selectProfileName(); + // if the user doesn't accept the dialog, remove the temporary profile // if they do accept the dialog, it will become a permanent profile if ( dialog.exec() != QDialog::Accepted ) SessionManager::instance()->deleteProfile(key); + else + { + SessionManager::instance()->setFavorite(key,true); + } } void ManageProfilesDialog::editSelected() { @@ -268,6 +276,21 @@ QString ManageProfilesDialog::selectedKey() const selectionModel()-> selectedIndexes().first().data( Qt::UserRole + 1 ).value(); } +void ManageProfilesDialog::updateFavoriteStatus(const QString& key , bool favorite) +{ + Q_ASSERT( _sessionModel ); + + const QModelIndex topIndex = _sessionModel->index(0,FavoriteStatusColumn); + + QModelIndexList list = _sessionModel->match( topIndex , ProfileKeyRole, + key ); + + foreach( QModelIndex index , list ) + { + const KIcon icon = favorite ? KIcon("favorites") : KIcon(); + _sessionModel->setData(index,icon,Qt::DecorationRole); + } +} ProfileItemDelegate::ProfileItemDelegate(QObject* parent) : QItemDelegate(parent) @@ -278,16 +301,11 @@ bool ProfileItemDelegate::editorEvent(QEvent* event,QAbstractItemModel* model, { if ( event->type() == QEvent::MouseButtonPress || event->type() == QEvent::KeyPress ) { - const QString& key = index.data(Qt::UserRole + 1).value(); + const QString& key = index.data(ManageProfilesDialog::ProfileKeyRole).value(); const bool isFavorite = !SessionManager::instance()->findFavorites().contains(key); SessionManager::instance()->setFavorite(key, isFavorite); - - if ( isFavorite ) - model->setData(index,KIcon("favorites"),Qt::DecorationRole); - else - model->setData(index,KIcon(),Qt::DecorationRole); } return true; diff --git a/src/ManageProfilesDialog.h b/src/ManageProfilesDialog.h index c34737a5a..5e26769df 100644 --- a/src/ManageProfilesDialog.h +++ b/src/ManageProfilesDialog.h @@ -48,11 +48,14 @@ class ManageProfilesDialog : public KDialog { Q_OBJECT +friend class ProfileItemDelegate; + public: /** Constructs a new profile type with the specified parent. */ ManageProfilesDialog(QWidget* parent = 0); virtual ~ManageProfilesDialog(); + protected: virtual void showEvent(QShowEvent* event); @@ -72,6 +75,8 @@ private slots: // session manager void updateTableModel(); + void updateFavoriteStatus(const QString& key , bool favorite); + private: QString selectedKey() const; // return the key associated with the currently selected // item in the profile table @@ -80,6 +85,10 @@ private: // their default / non-default profile status Ui::ManageProfilesDialog* _ui; QStandardItemModel* _sessionModel; + + static const int FavoriteStatusColumn = 1; + static const int ProfileKeyRole = Qt::UserRole + 1; + static const int ShortcutRole = Qt::UserRole + 1; }; class ProfileItemDelegate : public QItemDelegate diff --git a/src/ProcessInfo.cpp b/src/ProcessInfo.cpp index a854573d4..f93f1488b 100644 --- a/src/ProcessInfo.cpp +++ b/src/ProcessInfo.cpp @@ -65,6 +65,8 @@ QString ProcessInfo::format(const QString& input) const // search for and replace known markers output.replace("%u","NOT IMPLEMENTED YET"); output.replace("%n",name(&ok)); + output.replace("%c",formatCommand(name(&ok),arguments(&ok),ShortCommandFormat)); + output.replace("%C",formatCommand(name(&ok),arguments(&ok),LongCommandFormat)); output.replace("%D",currentDir(&ok)); output.replace("%d",formatShortDir(currentDir(&ok))); @@ -80,6 +82,13 @@ const char* ProcessInfo::DefaultCommonDirNames[] = "share" , "examples" , "icons" , "pics" , "plugins" , 0 }; +QString ProcessInfo::formatCommand(const QString& name, + const QVector& arguments, + CommandFormat format) const +{ + // TODO Implement me + return QStringList(QList::fromVector(arguments)).join(" "); +} QString ProcessInfo::formatShortDir(const QString& input) const { QString result; diff --git a/src/ProcessInfo.h b/src/ProcessInfo.h index a81b5dc8b..d7146ff3a 100644 --- a/src/ProcessInfo.h +++ b/src/ProcessInfo.h @@ -237,6 +237,15 @@ private: // space-constrained UI elements (eg. tabs) QString formatShortDir(const QString& dirPath) const; + enum CommandFormat + { + ShortCommandFormat, + LongCommandFormat + }; + // takes a process name and its arguments and produces formatted output + QString formatCommand(const QString& name , const QVector& arguments , + CommandFormat format) const; + // valid bits for _fields variable, ensure that // _fields is changed to an int if more than 8 fields are added enum FIELD_BITS diff --git a/src/ProfileList.cpp b/src/ProfileList.cpp index 5749f1011..e0cd1447e 100644 --- a/src/ProfileList.cpp +++ b/src/ProfileList.cpp @@ -27,6 +27,7 @@ // KDE #include +#include // Konsole #include "SessionManager.h" @@ -36,11 +37,17 @@ using namespace Konsole; ProfileList::ProfileList(bool addShortcuts , QObject* parent) : QObject(parent) , _addShortcuts(addShortcuts) + , _emptyListAction(0) { SessionManager* manager = SessionManager::instance(); // construct the list of favorite session types _group = new QActionGroup(this); + + // disabled action to be shown only when the list is empty + _emptyListAction = new QAction(i18n("No profiles available"),_group); + _emptyListAction->setEnabled(false); + QList list = manager->findFavorites().toList(); qSort(list); @@ -54,13 +61,25 @@ ProfileList::ProfileList(bool addShortcuts , QObject* parent) connect( _group , SIGNAL(triggered(QAction*)) , this , SLOT(triggered(QAction*)) ); + // listen for future changes to the session list connect( manager , SIGNAL(favoriteStatusChanged(const QString&,bool)) , this , SLOT(favoriteChanged(const QString&,bool)) ); connect( manager , SIGNAL(profileChanged(const QString&)) , this , SLOT(profileChanged(const QString&)) ); } +void ProfileList::updateEmptyAction() +{ + Q_ASSERT( _group ); + Q_ASSERT( _emptyListAction ); + // show empty list action when it is the only action + // in the group + const bool showEmptyAction = _group->actions().count() == 1; + + if ( showEmptyAction != _emptyListAction->isVisible() ) + _emptyListAction->setVisible(showEmptyAction); +} QAction* ProfileList::actionForKey(const QString& key) const { QListIterator iter(_group->actions()); @@ -119,6 +138,8 @@ void ProfileList::favoriteChanged(const QString& key,bool isFavorite) emit actionsChanged(_group->actions()); } } + + updateEmptyAction(); } void ProfileList::triggered(QAction* action) diff --git a/src/ProfileList.h b/src/ProfileList.h index 9ba15d224..f1cd80594 100644 --- a/src/ProfileList.h +++ b/src/ProfileList.h @@ -84,9 +84,13 @@ private slots: private: QAction* actionForKey(const QString& key) const; void updateAction(QAction* action , Profile* profile); + void updateEmptyAction(); QActionGroup* _group; bool _addShortcuts; + + // action to show when the list is empty + QAction* _emptyListAction; }; } diff --git a/src/TerminalDisplay.cpp b/src/TerminalDisplay.cpp index f5613e206..f9d213d0f 100644 --- a/src/TerminalDisplay.cpp +++ b/src/TerminalDisplay.cpp @@ -1470,8 +1470,8 @@ void TerminalDisplay::setScroll(int cursor, int slines) // // setting the range or value of a _scrollBar will always trigger // a repaint, so it should be avoided if it is not necessary - if ( _scrollBar->minimum() == 0 && - _scrollBar->maximum() == slines && + if ( _scrollBar->minimum() == 0 && + _scrollBar->maximum() == (slines - _lines) && _scrollBar->value() == cursor ) { //qDebug() << "no change in _scrollBar - skipping update";