#include #include #include #include #include #if QT_VERSION >= 0x050000 #include #endif #ifndef WITH_KF5 #include #include #include #include #else #include #include #include #include #include #include #include #include #include #define KAction QAction #define KIcon QIcon #endif #include "megasync-plugin.h" K_PLUGIN_FACTORY(MEGASyncPluginFactory, registerPlugin();) K_EXPORT_PLUGIN(MEGASyncPluginFactory("megasync-plugin")) typedef enum { STRING_UPLOAD = 0, STRING_GETLINK = 1, STRING_SHARE = 2, STRING_SEND = 3, STRING_VIEW_ON_MEGA = 5, STRING_VIEW_VERSIONS = 6 } StringID; enum { FILE_ERROR = 0, FILE_SYNCED = 1, FILE_PENDING = 2, FILE_SYNCING = 3, FILE_NOTFOUND = 9, }; const char OP_PATH_STATE = 'P'; //Path state const char OP_INIT = 'I'; //Init operation const char OP_END = 'E'; //End operation const char OP_UPLOAD = 'F'; //File-Folder upload const char OP_LINK = 'L'; //paste Link const char OP_SHARE = 'S'; //Share folder const char OP_SEND = 'C'; //Copy to user const char OP_STRING = 'T'; //Get Translated String const char OP_VIEW = 'V'; //View on MEGA const char OP_PREVIOUS = 'R'; //View previous versions MEGASyncPlugin::MEGASyncPlugin(QObject* parent, const QList & args): KAbstractFileItemActionPlugin(parent) { qDebug("MEGASYNCPLUGIN : Started"); Q_UNUSED(args); #if QT_VERSION < 0x050000 sockPath = QDir::home().path(); sockPath.append(QDir::separator()).append(".local/share/data/Mega Limited/MEGAsync/mega.socket"); #else sockPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); sockPath.append(QDir::separator()).append("data/Mega Limited/MEGAsync/mega.socket"); #endif sock.connectToServer(sockPath); } MEGASyncPlugin::~MEGASyncPlugin() { qDebug("MEGASYNCPLUGIN : Closing"); sock.close(); } QList MEGASyncPlugin::actions(const KFileItemListProperties & fileItemInfos, QWidget * parentWidget) { Q_UNUSED(parentWidget); QList actions; int state; int syncedFiles, syncedFolders, unsyncedFiles, unsyncedFolders; syncedFiles = syncedFolders = unsyncedFiles = unsyncedFolders = 0; // Make sure we only capture what the user has selected. selectedFilePath.clear(); selectedFilePaths.clear(); for( int i = 0; i < fileItemInfos.items().count(); i++) { KFileItem item = fileItemInfos.items().at(i); selectedFilePath = item.localPath(); selectedFilePaths << selectedFilePath; // get the state of selected file state = getState(); // count the number of synced / unsynced files and folders if (state == FILE_SYNCED || state == FILE_SYNCING || state == FILE_PENDING) { if (item.isDir()) { syncedFolders++; } else { syncedFiles++; } } else { if (item.isDir()) { unsyncedFolders++; } else { unsyncedFiles++; } } } // populate Menu KActionMenu * menuAction = new KActionMenu(this); menuAction->setText("MEGA"); actions << menuAction; // if there any unsynced files / folders selected if (unsyncedFiles || unsyncedFolders) { QAction* act = createChildAction(menuAction, STRING_UPLOAD, unsyncedFiles, unsyncedFolders); if (act) { connect(act, &QAction::triggered, this, &MEGASyncPlugin::uploadFiles); } } // if there any synced files / folders selected if (syncedFiles || syncedFolders) { QAction* act = createChildAction(menuAction, STRING_GETLINK, syncedFiles, syncedFolders); if (act) { // set menu icon //TODO: state refers to the last file. Does it make any sense?? if (state == FILE_SYNCED) act->setIcon(KIcon("mega-synced")); else if (state == FILE_PENDING) act->setIcon(KIcon("mega-pending")); else if (state == FILE_SYNCING) act->setIcon(KIcon("mega-syncing")); connect(act, SIGNAL(triggered()), this, SLOT(getLinks())); } } if (!unsyncedFiles && !unsyncedFolders && (syncedFiles + syncedFolders) == 1) { if (syncedFolders) { QAction* act = createChildAction(menuAction, STRING_VIEW_ON_MEGA); if (act) { connect(act, &QAction::triggered, this, &MEGASyncPlugin::viewOnMega); } } else { QAction* act = createChildAction(menuAction, STRING_VIEW_VERSIONS); if (act) { connect(act, &QAction::triggered, this, &MEGASyncPlugin::viewPreviousVersions); } } } qDebug("MEGASYNCPLUGIN : Created actions"); return actions; } int MEGASyncPlugin::getState() { QString res; QString cannonicalpath = QFileInfo(selectedFilePath).canonicalFilePath(); cannonicalpath.append((char)0x1C); cannonicalpath.append('1'); res = sendRequest(OP_PATH_STATE,cannonicalpath); return res.toInt(); } void MEGASyncPlugin::getLink() { if (sendRequest(OP_LINK, QFileInfo(selectedFilePath).canonicalFilePath()).size()) { sendRequest(OP_END, " "); } } void MEGASyncPlugin::getLinks() { for(int i = 0; iaddAction(act); return act; } return nullptr; } // send request and receive response from Extension server // Return newly-allocated response string QString MEGASyncPlugin::sendRequest(char type, QString command) { int waitTime = -1; // This (instead of a timeout) makes dolphin hang until the location for an upload is selected (will be corrected in megasync>3.0.1). // Otherwise megaync segafaults accesing client socket QString req; if(!sock.isOpen()) { sock.connectToServer(sockPath); if(!sock.waitForConnected(waitTime)) return QString(); } req.sprintf("%c:%s", type, command.toUtf8().constData()); qDebug("MEGASYNCPLUGIN : Sending request \"%s\"", req.toUtf8().constData()); sock.write(req.toUtf8()); sock.flush(); if(!sock.waitForReadyRead(waitTime)) { sock.close(); return QString(); } QString reply (sock.readAll().trimmed()); return reply; } #include "megasync-plugin.moc"