File indexing completed on 2024-04-28 04:20:53
0001 // SPDX-FileCopyrightText: 2012-2022 The KPhotoAlbum Development Team 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 #include "JobModel.h" 0006 0007 #include "CompletedJobInfo.h" 0008 #include "JobInfo.h" 0009 #include "JobManager.h" 0010 0011 #include <KLed> 0012 #include <KLocalizedString> 0013 #include <QApplication> 0014 #include <QBitmap> 0015 #include <QPainter> 0016 #include <QPixmap> 0017 #include <QTime> 0018 #include <QTimer> 0019 0020 namespace BackgroundTaskManager 0021 { 0022 0023 JobModel::JobModel(QObject *parent) 0024 : QAbstractTableModel(parent) 0025 , blinkStateOn(true) 0026 { 0027 connect(JobManager::instance(), SIGNAL(jobStarted(JobInterface *)), this, SLOT(jobStarted(JobInterface *))); 0028 connect(JobManager::instance(), SIGNAL(jobEnded(JobInterface *)), this, SLOT(jobEnded(JobInterface *))); 0029 0030 // Make the current task blink 0031 QTimer *timer = new QTimer(this); 0032 timer->start(500); 0033 connect(timer, &QTimer::timeout, this, &JobModel::heartbeat); 0034 } 0035 0036 JobModel::~JobModel() 0037 { 0038 qDeleteAll(m_previousJobs); 0039 } 0040 0041 int JobModel::rowCount(const QModelIndex &index) const 0042 { 0043 if (index.isValid()) 0044 return 0; 0045 else 0046 return m_previousJobs.count() + JobManager::instance()->activeJobCount() + JobManager::instance()->futureJobCount(); 0047 } 0048 0049 int JobModel::columnCount(const QModelIndex &) const 0050 { 0051 return 4; 0052 } 0053 0054 QVariant JobModel::data(const QModelIndex &index, int role) const 0055 { 0056 if (!index.isValid()) 0057 return QVariant(); 0058 0059 const int row = index.row(); 0060 const int col = index.column(); 0061 0062 JobInfo *current = info(row); 0063 if (!current) 0064 return QVariant(); 0065 0066 if (role == Qt::DisplayRole) { 0067 switch (col) { 0068 case IDCol: 0069 return current->jobIndex(); 0070 case TitleCol: 0071 return current->title(); 0072 case DetailsCol: 0073 return current->details(); 0074 case ElapsedCol: 0075 return current->elapsed(); 0076 default: 0077 return QVariant(); 0078 } 0079 } else if (role == Qt::DecorationRole && col == TitleCol) 0080 return statusImage(current->state); 0081 else if (role == Qt::TextAlignmentRole) 0082 return index.column() == IDCol ? Qt::AlignRight : Qt::AlignLeft; 0083 0084 return QVariant(); 0085 } 0086 0087 QVariant JobModel::headerData(int section, Qt::Orientation orientation, int role) const 0088 { 0089 if (orientation != Qt::Horizontal || role != Qt::DisplayRole) 0090 return QVariant(); 0091 switch (section) { 0092 case IDCol: 0093 return i18nc("@title:column Background job id", "ID"); 0094 case TitleCol: 0095 return i18nc("@title:column Background job title", "Title"); 0096 case DetailsCol: 0097 return i18nc("@title:column Additional information on background job", "Details"); 0098 case ElapsedCol: 0099 return i18nc("@title:column Elapsed time", "Elapsed"); 0100 default: 0101 return QVariant(); 0102 } 0103 } 0104 0105 void JobModel::reset() 0106 { 0107 // FIXME: this is just a stand-in replacement for a call to the deprecated 0108 // QAbstractTableModel::reset(); 0109 // fix this by replacing the calls to reset() using: 0110 // beginInsertRows() 0111 // beginRemoveRows() 0112 // beginMoveRows() 0113 beginResetModel(); 0114 endResetModel(); 0115 } 0116 0117 void JobModel::jobEnded(JobInterface *job) 0118 { 0119 m_previousJobs.append(new CompletedJobInfo(job)); 0120 reset(); 0121 } 0122 0123 void JobModel::jobStarted(JobInterface *job) 0124 { 0125 connect(job, SIGNAL(changed()), this, SLOT(reset())); 0126 reset(); 0127 } 0128 0129 void JobModel::heartbeat() 0130 { 0131 beginResetModel(); 0132 blinkStateOn = !blinkStateOn; 0133 // optional improvement: Q_EMIT dataChanged for running jobs only 0134 endResetModel(); 0135 } 0136 0137 JobInfo *JobModel::info(int row) const 0138 { 0139 if (row < m_previousJobs.count()) 0140 return m_previousJobs[row]; 0141 0142 row -= m_previousJobs.count(); 0143 if (row < JobManager::instance()->activeJobCount()) 0144 return JobManager::instance()->activeJob(row); 0145 0146 row -= JobManager::instance()->activeJobCount(); 0147 Q_ASSERT(row < JobManager::instance()->futureJobCount()); 0148 return JobManager::instance()->futureJob(row); 0149 } 0150 0151 QPixmap JobModel::statusImage(JobInfo::State state) const 0152 { 0153 QColor color; 0154 if (state == JobInfo::Running) 0155 color = blinkStateOn ? Qt::green : qApp->palette().mid().color(); 0156 else if (state == JobInfo::Completed) 0157 color = Qt::red; 0158 else 0159 color = QColor(Qt::yellow).darker(); 0160 0161 KLed led; 0162 led.setColor(color); 0163 0164 QPixmap pixmap = led.grab(); 0165 // creating the mask by heuristic is expensive, so do it only once: 0166 static QBitmap s_ledMask = pixmap.createHeuristicMask(); 0167 pixmap.setMask(s_ledMask); 0168 0169 return pixmap; 0170 } 0171 0172 } // namespace BackgroundTaskManager 0173 // vi:expandtab:tabstop=4 shiftwidth=4: 0174 0175 #include "moc_JobModel.cpp"