Warning, file /network/krdc/remotedesktopsmodel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2008 Urs Wolfer <uwolfer@kde.org> 0003 SPDX-FileCopyrightText: 2009 Tony Murray <murraytony@gmail.com> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "remotedesktopsmodel.h" 0009 #include "krdc_debug.h" 0010 0011 #include <KLocalizedString> 0012 #include <KFormat> 0013 #ifdef BUILD_ZEROCONF 0014 #include <kdnssd_version.h> 0015 #include <KDNSSD/ServiceBrowser> 0016 #include <KDNSSD/RemoteService> 0017 #endif 0018 #include <QLoggingCategory> 0019 #include <QStandardPaths> 0020 #include <QObject> 0021 0022 RemoteDesktopsModel::RemoteDesktopsModel(QObject *parent, KBookmarkManager *manager) 0023 : QAbstractTableModel(parent) 0024 { 0025 m_manager = manager; 0026 m_manager->setUpdate(true); 0027 connect(m_manager, SIGNAL(changed(QString,QString)), SLOT(bookmarksChanged())); 0028 buildModelFromBookmarkGroup(m_manager->root()); 0029 0030 #ifdef BUILD_ZEROCONF 0031 // Add RDP and NX if they start announcing via Zeroconf: 0032 m_protocols[QLatin1String("_rfb._tcp")] = QLatin1String("vnc"); 0033 0034 zeroconfBrowser = new KDNSSD::ServiceBrowser(QLatin1String("_rfb._tcp"), true); 0035 connect(zeroconfBrowser, SIGNAL(finished()), this, SLOT(servicesChanged())); 0036 zeroconfBrowser->startBrowse(); 0037 qCDebug(KRDC) << "Browsing for zeroconf hosts."; 0038 #endif 0039 } 0040 0041 RemoteDesktopsModel::~RemoteDesktopsModel() 0042 { 0043 } 0044 0045 int RemoteDesktopsModel::columnCount(const QModelIndex &) const 0046 { 0047 return 6; // same as count of RemoteDesktopsModel::DisplayItems enum 0048 } 0049 0050 int RemoteDesktopsModel::rowCount(const QModelIndex &) const 0051 { 0052 return remoteDesktops.size(); 0053 } 0054 0055 Qt::ItemFlags RemoteDesktopsModel::flags(const QModelIndex &index) const 0056 { 0057 if (!index.isValid()) 0058 return Qt::NoItemFlags; 0059 if (index.column() == RemoteDesktopsModel::Favorite) { 0060 return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; 0061 } 0062 return Qt::ItemIsEnabled; 0063 } 0064 0065 bool RemoteDesktopsModel::setData(const QModelIndex &index, const QVariant &value, int role) 0066 { 0067 if (index.isValid() && role == Qt::CheckStateRole && index.column() == RemoteDesktopsModel::Favorite) { 0068 bool checked = (Qt::CheckState)value.toUInt() == Qt::Checked; 0069 remoteDesktops[index.row()].favorite = checked; 0070 0071 RemoteDesktop rd = remoteDesktops.at(index.row()); 0072 if (checked) { 0073 KBookmarkGroup root = m_manager->root(); 0074 root.addBookmark(rd.title, QUrl(rd.url), QString()); 0075 m_manager->emitChanged(root); 0076 } else { 0077 BookmarkManager::removeByUrl(m_manager, rd.url, true, rd.title); 0078 } 0079 return true; 0080 } 0081 return false; 0082 } 0083 0084 QVariant RemoteDesktopsModel::data(const QModelIndex &index, int role) const 0085 { 0086 if (!index.isValid()) 0087 return QVariant(); 0088 0089 RemoteDesktop item = remoteDesktops.at(index.row()); 0090 0091 switch (role) { 0092 case Qt::DisplayRole: 0093 switch (index.column()) { 0094 case RemoteDesktopsModel::Favorite: 0095 return item.favorite; 0096 case RemoteDesktopsModel::Title: 0097 return item.title; 0098 case RemoteDesktopsModel::LastConnected: 0099 return QVariant(item.lastConnected); 0100 case RemoteDesktopsModel::VisitCount: 0101 return item.visits; 0102 case RemoteDesktopsModel::Created: 0103 if (item.created.isNull()) return QVariant(); 0104 return QLocale().toString(item.created.toLocalTime(), QLocale::FormatType::ShortFormat); 0105 case RemoteDesktopsModel::Source: 0106 switch (item.source) { 0107 case RemoteDesktop::Bookmarks: 0108 return i18nc("Where each displayed link comes from", "Bookmarks"); 0109 case RemoteDesktop::History: 0110 return i18nc("Where each displayed link comes from", "History"); 0111 case RemoteDesktop::Zeroconf: 0112 return i18nc("Where each displayed link comes from", "Zeroconf"); 0113 case RemoteDesktop::None: 0114 return i18nc("Where each displayed link comes from", "None"); 0115 } 0116 // fall-through 0117 default: 0118 return QVariant(); 0119 } 0120 0121 case Qt::CheckStateRole: 0122 if (index.column() == RemoteDesktopsModel::Favorite) 0123 return item.favorite ? Qt::Checked : Qt::Unchecked; 0124 return QVariant(); 0125 0126 case Qt::ToolTipRole: 0127 switch(index.column()) { 0128 case RemoteDesktopsModel::Favorite: 0129 if (item.favorite) { 0130 return i18nc("Remove the selected url from the bookarks menu", "Remove the bookmark for %1.", item.title); 0131 } else { 0132 return i18nc("Add the selected url to the bookmarks menu", "Bookmark %1.", item.title); 0133 } 0134 case RemoteDesktopsModel::LastConnected: 0135 if (!item.lastConnected.isNull()) { 0136 return QLocale().toString(item.lastConnected.toLocalTime(), QLocale::FormatType::LongFormat); 0137 } 0138 break; // else show default tooltip 0139 case RemoteDesktopsModel::Created: 0140 if (!item.created.isNull()) { 0141 return QLocale().toString(item.lastConnected.toLocalTime(), QLocale::FormatType::LongFormat); 0142 } 0143 break; // else show default tooltip 0144 default: 0145 break; 0146 } 0147 return item.url; //use the url for the tooltip 0148 0149 case 10001: //url for dockwidget 0150 return item.url; 0151 0152 case 10002: //filter 0153 return QUrl::fromPercentEncoding(QString(item.url + item.title).toUtf8()); // return both user visible title and url data, percent encoded 0154 0155 case 10003: //title for dockwidget 0156 return item.title; 0157 0158 default: 0159 return QVariant(); 0160 } 0161 } 0162 0163 QVariant RemoteDesktopsModel::headerData(int section, Qt::Orientation orientation, 0164 int role) const 0165 { 0166 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { 0167 switch (section) { 0168 case RemoteDesktopsModel::Favorite: 0169 return QVariant(); // the favorite column is to small for a header 0170 case RemoteDesktopsModel::Title: 0171 return i18nc("Header of the connections list, title/url for remote connection", "Remote Desktop"); 0172 case RemoteDesktopsModel::LastConnected: 0173 return i18nc("Header of the connections list, the last time this connection was initiated", "Last Connected"); 0174 case RemoteDesktopsModel::VisitCount: 0175 return i18nc("Header of the connections list, the number of times this connection has been visited", "Visits"); 0176 case RemoteDesktopsModel::Created: 0177 return i18nc("Header of the connections list, the time when this entry was created", "Created"); 0178 case RemoteDesktopsModel::Source: 0179 return i18nc("Header of the connections list, where this entry comes from", "Source"); 0180 } 0181 } 0182 return QVariant(); 0183 } 0184 0185 // does not trigger view update, you must do this by hand after using this function 0186 void RemoteDesktopsModel::removeAllItemsFromSources(RemoteDesktop::Sources sources) 0187 { 0188 QMutableListIterator<RemoteDesktop> iter(remoteDesktops); 0189 while (iter.hasNext()) { 0190 iter.next(); 0191 // if it matches any of the specified sources, remove it 0192 if ((iter.value().source & sources) > 0) 0193 iter.remove(); 0194 } 0195 } 0196 0197 void RemoteDesktopsModel::bookmarksChanged() 0198 { 0199 removeAllItemsFromSources(RemoteDesktop::Bookmarks | RemoteDesktop::History); 0200 buildModelFromBookmarkGroup(m_manager->root()); 0201 beginResetModel(); 0202 endResetModel(); 0203 } 0204 0205 // Danger Will Roobinson, confusing code ahead! 0206 void RemoteDesktopsModel::buildModelFromBookmarkGroup(const KBookmarkGroup &group) 0207 { 0208 KBookmark bm = group.first(); 0209 while (!bm.isNull()) { 0210 if (bm.isGroup()) { 0211 // recurse subfolders and treat it special if it is the history folder 0212 buildModelFromBookmarkGroup(bm.toGroup()); 0213 } else { // not a group 0214 0215 RemoteDesktop item; 0216 item.title = bm.fullText(); 0217 item.url = bm.url().url(); 0218 int index = remoteDesktops.indexOf(item); //search for this url to see if we need to update it 0219 bool newItem = index < 0; // do we need to create a new item? 0220 0221 // we want to merge all copies of a url into one link, so if the item exists, update it 0222 if (group.metaDataItem(QLatin1String("krdc-history")) == QLatin1String("historyfolder")) { 0223 // set source and favorite (will override later if needed) 0224 item.source = RemoteDesktop::History; 0225 item.favorite = false; 0226 0227 // since we are in the history folder collect statistics and add them 0228 QDateTime connected = QDateTime(); 0229 QDateTime created = QDateTime(); 0230 bool ok = false; 0231 // first the created datetime 0232 created = QDateTime::fromSecsSinceEpoch(bm.metaDataItem(QLatin1String("time_added")).toLongLong(&ok)); 0233 if (ok) (newItem ? item : remoteDesktops[index]).created = created; 0234 // then the last visited datetime 0235 ok = false; 0236 connected = QDateTime::fromSecsSinceEpoch(bm.metaDataItem(QLatin1String("time_visited")).toLongLong(&ok)); 0237 if (ok) (newItem ? item : remoteDesktops[index]).lastConnected = connected; 0238 // finally the visited count 0239 ok = false; 0240 int visits = bm.metaDataItem(QLatin1String("visit_count")).toInt(&ok); 0241 if (ok) (newItem ? item : remoteDesktops[index]).visits = visits; 0242 } else { 0243 if (newItem) { 0244 // if this is a new item, just add the rest of the required data 0245 item.lastConnected = QDateTime(); 0246 item.created = QDateTime(); 0247 item.visits = 0; 0248 item.favorite = true; 0249 item.source = RemoteDesktop::Bookmarks; 0250 } else { 0251 // otherwise override these fields with the info from the bookmark 0252 remoteDesktops[index].title = bm.fullText(); 0253 remoteDesktops[index].favorite = true; 0254 remoteDesktops[index].source = RemoteDesktop::Bookmarks; 0255 } 0256 } 0257 // if we have a new item, add it 0258 if (newItem) 0259 remoteDesktops.append(item); 0260 } 0261 bm = group.next(bm); // next item in the group 0262 } 0263 } 0264 0265 #ifdef BUILD_ZEROCONF 0266 void RemoteDesktopsModel::servicesChanged() 0267 { 0268 //redo list because it is easier than finding and removing one that disappeared 0269 const QList<KDNSSD::RemoteService::Ptr> services = zeroconfBrowser->services(); 0270 QUrl url; 0271 removeAllItemsFromSources(RemoteDesktop::Zeroconf); 0272 for (const KDNSSD::RemoteService::Ptr& service : services) { 0273 url.setScheme(m_protocols[service->type()].toLower()); 0274 url.setHost(service->hostName()); 0275 url.setPort(service->port()); 0276 0277 RemoteDesktop item; 0278 item.url = url.url(); 0279 0280 if (!remoteDesktops.contains(item)) { 0281 item.title = service->serviceName(); 0282 item.source = RemoteDesktop::Zeroconf; 0283 item.created = QDateTime::currentDateTime(); 0284 item.favorite = false; 0285 item.visits = 0; 0286 remoteDesktops.append(item); 0287 } 0288 } 0289 beginResetModel(); 0290 endResetModel(); 0291 } 0292 #endif 0293