1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
|
/****************************************************************************
**
** Copyright (C) 2008 Urs Wolfer <uwolfer @ kde.org>
** Copyright (C) 2009 Tony Murray <murraytony@gmail.com>
**
** This file is part of KDE.
**
** 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; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA.
**
****************************************************************************/
#include "remotedesktopsmodel.h"
#include "krdc_debug.h"
#include <KLocalizedString>
#include<KCoreAddons/KFormat>
#include <DNSSD/ServiceBrowser>
#include <QDateTime>
#include <QLoggingCategory>
#include <QStandardPaths>
#include <QObject>
RemoteDesktopsModel::RemoteDesktopsModel(QObject *parent, KBookmarkManager *manager)
: QAbstractTableModel(parent)
{
m_manager = manager;
m_manager->setUpdate(true);
connect(m_manager, SIGNAL(changed(QString,QString)), SLOT(bookmarksChanged()));
buildModelFromBookmarkGroup(m_manager->root());
#ifdef BUILD_ZEROCONF
// Add RDP and NX if they start announcing via Zeroconf:
m_protocols[QLatin1String("_rfb._tcp")] = QLatin1String("vnc");
zeroconfBrowser = new KDNSSD::ServiceBrowser(QLatin1String("_rfb._tcp"), true);
connect(zeroconfBrowser, SIGNAL(finished()), this, SLOT(servicesChanged()));
zeroconfBrowser->startBrowse();
qCDebug(KRDC) << "Browsing for zeroconf hosts.";
#endif
}
RemoteDesktopsModel::~RemoteDesktopsModel()
{
}
int RemoteDesktopsModel::columnCount(const QModelIndex &) const
{
return 6; // same as count of RemoteDesktopsModel::DisplayItems enum
}
int RemoteDesktopsModel::rowCount(const QModelIndex &) const
{
return remoteDesktops.size();
}
Qt::ItemFlags RemoteDesktopsModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;
if (index.column() == RemoteDesktopsModel::Favorite) {
return Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
}
return Qt::ItemIsEnabled;
}
bool RemoteDesktopsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::CheckStateRole && index.column() == RemoteDesktopsModel::Favorite) {
bool checked = (Qt::CheckState)value.toUInt() == Qt::Checked;
remoteDesktops[index.row()].favorite = checked;
RemoteDesktop rd = remoteDesktops.at(index.row());
if (checked) {
KBookmarkGroup root = m_manager->root();
root.addBookmark(rd.title, QUrl(rd.url), QString());
m_manager->emitChanged(root);
} else {
BookmarkManager::removeByUrl(m_manager, rd.url, true, rd.title);
}
return true;
}
return false;
}
QVariant RemoteDesktopsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
RemoteDesktop item = remoteDesktops.at(index.row());
switch (role) {
case Qt::DisplayRole:
switch (index.column()) {
case RemoteDesktopsModel::Favorite:
return item.favorite;
case RemoteDesktopsModel::Title:
return item.title;
case RemoteDesktopsModel::LastConnected:
return QVariant(item.lastConnected);
case RemoteDesktopsModel::VisitCount:
return item.visits;
case RemoteDesktopsModel::Created:
if (item.created.isNull()) return QVariant();
return QLocale().toString(item.created.toLocalTime(), QLocale::FormatType::ShortFormat);
case RemoteDesktopsModel::Source:
switch (item.source) {
case RemoteDesktop::Bookmarks:
return i18nc("Where each displayed link comes from", "Bookmarks");
case RemoteDesktop::History:
return i18nc("Where each displayed link comes from", "History");
case RemoteDesktop::Zeroconf:
return i18nc("Where each displayed link comes from", "Zeroconf");
case RemoteDesktop::None:
return i18nc("Where each displayed link comes from", "None");
}
default:
return QVariant();
}
case Qt::CheckStateRole:
if (index.column() == RemoteDesktopsModel::Favorite)
return item.favorite ? Qt::Checked : Qt::Unchecked;
return QVariant();
case Qt::ToolTipRole:
switch(index.column()) {
case RemoteDesktopsModel::Favorite:
if (item.favorite) {
return i18nc("Remove the selected url from the bookarks menu", "Remove the bookmark for %1.", item.title);
} else {
return i18nc("Add the selected url to the bookmarks menu", "Bookmark %1.", item.title);
}
case RemoteDesktopsModel::LastConnected:
if (!item.lastConnected.isNull()) {
return QLocale().toString(item.lastConnected.toLocalTime(), QLocale::FormatType::LongFormat);
}
break; // else show default tooltip
case RemoteDesktopsModel::Created:
if (!item.created.isNull()) {
return QLocale().toString(item.lastConnected.toLocalTime(), QLocale::FormatType::LongFormat);
}
break; // else show default tooltip
default:
break;
}
return item.url; //use the url for the tooltip
case 10001: //url for dockwidget
return item.url;
case 10002: //filter
return QUrl::fromPercentEncoding(QString(item.url + item.title).toUtf8()); // return both user visible title and url data, percent encoded
case 10003: //title for dockwidget
return item.title;
default:
return QVariant();
}
}
QVariant RemoteDesktopsModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case RemoteDesktopsModel::Favorite:
return QVariant(); // the favorite column is to small for a header
case RemoteDesktopsModel::Title:
return i18nc("Header of the connections list, title/url for remote connection", "Remote Desktop");
case RemoteDesktopsModel::LastConnected:
return i18nc("Header of the connections list, the last time this connection was initiated", "Last Connected");
case RemoteDesktopsModel::VisitCount:
return i18nc("Header of the connections list, the number of times this connection has been visited", "Visits");
case RemoteDesktopsModel::Created:
return i18nc("Header of the connections list, the time when this entry was created", "Created");
case RemoteDesktopsModel::Source:
return i18nc("Header of the connections list, where this entry comes from", "Source");
}
}
return QVariant();
}
// does not trigger view update, you must do this by hand after using this function
void RemoteDesktopsModel::removeAllItemsFromSources(RemoteDesktop::Sources sources)
{
QMutableListIterator<RemoteDesktop> iter(remoteDesktops);
while (iter.hasNext()) {
iter.next();
// if it matches any of the specified sources, remove it
if ((iter.value().source & sources) > 0)
iter.remove();
}
}
void RemoteDesktopsModel::bookmarksChanged()
{
removeAllItemsFromSources(RemoteDesktop::Bookmarks | RemoteDesktop::History);
buildModelFromBookmarkGroup(m_manager->root());
beginResetModel();
endResetModel();
}
// Danger Will Roobinson, confusing code ahead!
void RemoteDesktopsModel::buildModelFromBookmarkGroup(const KBookmarkGroup &group)
{
KBookmark bm = group.first();
while (!bm.isNull()) {
if (bm.isGroup()) {
// recurse subfolders and treat it special if it is the history folder
buildModelFromBookmarkGroup(bm.toGroup());
} else { // not a group
RemoteDesktop item;
item.title = bm.fullText();
item.url = bm.url().url();
int index = remoteDesktops.indexOf(item); //search for this url to see if we need to update it
bool newItem = index < 0; // do we need to create a new item?
// we want to merge all copies of a url into one link, so if the item exists, update it
if (group.metaDataItem(QLatin1String("krdc-history")) == QLatin1String("historyfolder")) {
// set source and favorite (will override later if needed)
item.source = RemoteDesktop::History;
item.favorite = false;
// since we are in the history folder collect statitics and add them
QDateTime connected = QDateTime();
QDateTime created = QDateTime();
bool ok = false;
// first the created datetime
created.setTime_t(bm.metaDataItem(QLatin1String("time_added")).toLongLong(&ok));
if (ok) (newItem ? item : remoteDesktops[index]).created = created;
// then the last visited datetime
ok = false;
connected.setTime_t(bm.metaDataItem(QLatin1String("time_visited")).toLongLong(&ok));
if (ok) (newItem ? item : remoteDesktops[index]).lastConnected = connected;
// finally the visited count
ok = false;
int visits = bm.metaDataItem(QLatin1String("visit_count")).toInt(&ok);
if (ok) (newItem ? item : remoteDesktops[index]).visits = visits;
} else {
if (newItem) {
// if this is a new item, just add the rest of the required data
item.lastConnected = QDateTime();
item.created = QDateTime();
item.visits = 0;
item.favorite = true;
item.source = RemoteDesktop::Bookmarks;
} else {
// otherwise override these fields with the info from the bookmark
remoteDesktops[index].title = bm.fullText();
remoteDesktops[index].favorite = true;
remoteDesktops[index].source = RemoteDesktop::Bookmarks;
}
}
// if we have a new item, add it
if (newItem)
remoteDesktops.append(item);
}
bm = group.next(bm); // next item in the group
}
}
#ifdef BUILD_ZEROCONF
void RemoteDesktopsModel::servicesChanged()
{
//redo list because it is easier than finding and removing one that disappeared
QList<KDNSSD::RemoteService::Ptr> services = zeroconfBrowser->services();
QUrl url;
removeAllItemsFromSources(RemoteDesktop::Zeroconf);
foreach(KDNSSD::RemoteService::Ptr service, services) {
url.setScheme(m_protocols[service->type()].toLower());
url.setHost(service->hostName());
url.setPort(service->port());
RemoteDesktop item;
item.url = url.url();
if (!remoteDesktops.contains(item)) {
item.title = service->serviceName();
item.source = RemoteDesktop::Zeroconf;
item.created = QDateTime::currentDateTime();
item.favorite = false;
item.visits = 0;
remoteDesktops.append(item);
}
}
beginResetModel();
endResetModel();
}
#endif
|