File indexing completed on 2024-05-05 04:21:42
0001 // SPDX-FileCopyrightText: 2014-2022 Jesper K. Pedersen <blackie@kde.org> 0002 // 0003 // SPDX-License-Identifier: GPL-2.0-or-later 0004 0005 #include "RemoteInterface.h" 0006 0007 #include "Action.h" 0008 #include "Client.h" 0009 #include "ImageDetails.h" 0010 #include "ImageStore.h" 0011 #include "RemoteCommand.h" 0012 #include "ScreenInfo.h" 0013 #include "Settings.h" 0014 0015 #include <QBuffer> 0016 #include <QCoreApplication> 0017 #include <QDataStream> 0018 #include <QHostInfo> 0019 #include <QLabel> 0020 #include <QNetworkInterface> 0021 #include <QTcpSocket> 0022 #include <qimage.h> 0023 0024 #include <memory> 0025 0026 using namespace RemoteControl; 0027 0028 RemoteInterface::RemoteInterface() 0029 : m_categories(new CategoryModel(this)) 0030 , m_categoryItems(new ThumbnailModel(this)) 0031 , m_thumbnailModel(new ThumbnailModel(this)) 0032 , m_discoveryModel(new DiscoveryModel(this)) 0033 { 0034 m_connection = new Client; 0035 connect(m_connection, SIGNAL(gotCommand(RemoteCommand)), this, SLOT(handleCommand(RemoteCommand))); 0036 connect(m_connection, &Client::gotConnected, this, &RemoteInterface::connectionChanged); 0037 connect(m_connection, &Client::gotConnected, this, &RemoteInterface::requestInitialData); 0038 connect(m_connection, &Client::disconnected, this, &RemoteInterface::gotDisconnected); 0039 connect(m_connection, &Client::disconnected, this, &RemoteInterface::connectionChanged); 0040 qRegisterMetaType<RemoteControl::CategoryModel *>("RemoteControl::CategoryModel*"); 0041 qRegisterMetaType<RemoteControl::ThumbnailModel *>("ThumbnailModel*"); 0042 qRegisterMetaType<RemoteControl::DiscoveryModel *>("DiscoveryModel*"); 0043 0044 QTimer::singleShot(1000, this, SLOT(pushAwayFromStartupState())); 0045 } 0046 0047 void RemoteInterface::setCurrentPage(Page page) 0048 { 0049 if (m_currentPage != page) { 0050 m_currentPage = page; 0051 Q_EMIT currentPageChanged(); 0052 } 0053 } 0054 0055 void RemoteInterface::setListCategoryValues(const QStringList &values) 0056 { 0057 if (m_listCategoryValues != values) { 0058 m_listCategoryValues = values; 0059 Q_EMIT listCategoryValuesChanged(); 0060 } 0061 } 0062 0063 void RemoteInterface::requestHomePageImages() 0064 { 0065 m_connection->sendCommand(StaticImageRequest(ScreenInfo::instance().overviewIconSize())); 0066 } 0067 0068 void RemoteInterface::gotDisconnected() 0069 { 0070 setCurrentPage(Page::UnconnectedPage); 0071 } 0072 0073 void RemoteInterface::setHomePageImages(const StaticImageResult &command) 0074 { 0075 m_homeImage = command.homeIcon; 0076 Q_EMIT homeImageChanged(); 0077 0078 m_kphotoalbumImage = command.kphotoalbumIcon; 0079 Q_EMIT kphotoalbumImageChange(); 0080 0081 m_discoveryImage = command.discoverIcon; 0082 Q_EMIT discoveryImageChanged(); 0083 } 0084 0085 RemoteInterface &RemoteInterface::instance() 0086 { 0087 static RemoteInterface interface; 0088 return interface; 0089 } 0090 0091 bool RemoteInterface::isConnected() const 0092 { 0093 return m_connection->isConnected(); 0094 } 0095 0096 void RemoteInterface::sendCommand(const RemoteCommand &command) 0097 { 0098 m_connection->sendCommand(command); 0099 } 0100 0101 QString RemoteInterface::currentCategory() const 0102 { 0103 return m_search.currentCategory(); 0104 } 0105 0106 QImage RemoteInterface::discoveryImage() const 0107 { 0108 return m_discoveryImage; 0109 } 0110 0111 void RemoteInterface::setActiveThumbnailModel(RemoteInterface::ModelType type) 0112 { 0113 ThumbnailModel *newModel = (type == ModelType::Thumbnail ? m_thumbnailModel : m_discoveryModel); 0114 if (newModel != m_activeThumbnailModel) { 0115 m_activeThumbnailModel = newModel; 0116 activeThumbnailModelChanged(); 0117 } 0118 m_activeThumbnailModel->setImages({}); 0119 } 0120 0121 void RemoteInterface::goHome() 0122 { 0123 requestInitialData(); 0124 } 0125 0126 void RemoteInterface::goBack() 0127 { 0128 if (m_history.canGoBack()) 0129 m_history.goBackward(); 0130 else 0131 qApp->quit(); 0132 } 0133 0134 void RemoteInterface::goForward() 0135 { 0136 if (m_history.canGoForward()) 0137 m_history.goForward(); 0138 } 0139 0140 void RemoteInterface::selectCategory(const QString &category, int type) 0141 { 0142 m_search.addCategory(category); 0143 m_history.push(std::unique_ptr<Action>(new ShowCategoryValueAction(m_search, static_cast<CategoryViewType>(type)))); 0144 } 0145 0146 void RemoteInterface::selectCategoryValue(const QString &value) 0147 { 0148 m_search.addValue(value); 0149 m_history.push(std::unique_ptr<Action>(new ShowThumbnailsAction(m_search))); 0150 } 0151 0152 void RemoteInterface::showThumbnails() 0153 { 0154 m_history.push(std::unique_ptr<Action>(new ShowThumbnailsAction(m_search))); 0155 } 0156 0157 void RemoteInterface::showImage(int imageId) 0158 { 0159 m_history.push(std::unique_ptr<Action>(new ShowImagesAction(imageId, m_search))); 0160 } 0161 0162 void RemoteInterface::requestDetails(int imageId) 0163 { 0164 m_connection->sendCommand(ImageDetailsRequest(imageId)); 0165 } 0166 0167 void RemoteInterface::activateSearch(const QString &search) 0168 { 0169 QStringList list = search.split(";;;"); 0170 QString category = list[0]; 0171 QString item = list[1]; 0172 SearchInfo result; 0173 result.addCategory(category); 0174 result.addValue(item); 0175 m_history.push(std::unique_ptr<Action>(new ShowThumbnailsAction(result))); 0176 } 0177 0178 void RemoteInterface::doDiscovery() 0179 { 0180 m_history.push(std::unique_ptr<Action>(new DiscoverAction(m_search, m_discoveryModel))); 0181 } 0182 0183 void RemoteInterface::showOverviewPage() 0184 { 0185 m_history.push(std::unique_ptr<Action>(new ShowOverviewAction(m_search))); 0186 } 0187 0188 void RemoteInterface::setToken(int imageId, const QString &token) 0189 { 0190 sendCommand(ToggleTokenRequest(imageId, token, ToggleTokenRequest::On)); 0191 } 0192 0193 void RemoteInterface::removeToken(int imageId, const QString &token) 0194 { 0195 sendCommand(ToggleTokenRequest(imageId, token, ToggleTokenRequest::Off)); 0196 } 0197 0198 void RemoteInterface::rerequestOverviewPageData() 0199 { 0200 requestHomePageImages(); 0201 m_history.rerunTopItem(); 0202 } 0203 0204 void RemoteInterface::pushAwayFromStartupState() 0205 { 0206 // Avoid that the "not connected page" show for a few milliseconds while the connection is being set up. 0207 if (!isConnected() && m_currentPage == Types::Startup) 0208 setCurrentPage(Types::UnconnectedPage); 0209 } 0210 0211 void RemoteInterface::setCurrentView(int imageId) 0212 { 0213 Q_EMIT jumpToImage(m_activeThumbnailModel->indexOf(imageId)); 0214 } 0215 0216 QString RemoteInterface::networkAddress() const 0217 { 0218 QStringList result; 0219 for (const QHostAddress &address : QNetworkInterface::allAddresses()) { 0220 if (address.isLoopback() || address.toIPv4Address() == 0) 0221 continue; 0222 result.append(address.toString()); 0223 } 0224 return result.join(QStringLiteral(", ")); 0225 } 0226 0227 QStringList RemoteInterface::tokens() const 0228 { 0229 // FIXME: in KPA the tokens category is now retrieved using categoryForSpecial 0230 return ImageDetails::instance().itemsOfCategory(QStringLiteral("Tokens")); 0231 } 0232 0233 void RemoteInterface::requestInitialData() 0234 { 0235 requestHomePageImages(); 0236 m_history.push(std::unique_ptr<Action>(new ShowOverviewAction({}))); 0237 } 0238 0239 void RemoteInterface::handleCommand(const RemoteCommand &command) 0240 { 0241 if (command.commandType() == CommandType::ThumbnailResult) 0242 updateImage(static_cast<const ThumbnailResult &>(command)); 0243 else if (command.commandType() == CommandType::CategoryListResult) 0244 updateCategoryList(static_cast<const CategoryListResult &>(command)); 0245 else if (command.commandType() == CommandType::SearchResult) 0246 gotSearchResult(static_cast<const SearchResult &>(command)); 0247 else if (command.commandType() == CommandType::TimeCommand) 0248 ; // Used for debugging, it will print time stamp when decoded 0249 else if (command.commandType() == CommandType::ImageDetailsResult) { 0250 ImageDetails::instance().setData(static_cast<const ImageDetailsResult &>(command)); 0251 Q_EMIT tokensChanged(); 0252 } else if (command.commandType() == CommandType::CategoryItemsResult) 0253 setListCategoryValues(static_cast<const CategoryItemsResult &>(command).items); 0254 else if (command.commandType() == CommandType::StaticImageResult) 0255 setHomePageImages(static_cast<const StaticImageResult &>(command)); 0256 else 0257 qFatal("Unhandled command"); 0258 } 0259 0260 void RemoteInterface::updateImage(const ThumbnailResult &command) 0261 { 0262 ImageStore::instance().updateImage(command.imageId, command.image, command.label, command.type); 0263 } 0264 0265 void RemoteInterface::updateCategoryList(const CategoryListResult &command) 0266 { 0267 ScreenInfo::instance().setCategoryCount(command.categories.count()); 0268 m_categories->setCategories(command.categories); 0269 } 0270 0271 void RemoteInterface::gotSearchResult(const SearchResult &result) 0272 { 0273 if (result.type == SearchType::Images) { 0274 m_activeThumbnailModel->setImages(result.result); 0275 } else if (result.type == SearchType::CategoryItems) { 0276 m_categoryItems->setImages(result.result); 0277 } 0278 } 0279 0280 #include "moc_RemoteInterface.cpp"