99581bc990
- Updated header inclusions from QtGui to QtWidgets for consistency and compatibility with Qt 5 and later. - Replaced deprecated QApplication::desktop() with QApplication::primaryScreen() for obtaining screen DPI. - Modified MyOutputHandler to use QMessageLogContext and QString for improved logging. - Changed QMatrix to QTransform for image rotation in ImageCutout class. - Updated various debug statements to use toLocal8Bit() instead of toAscii() for better string handling. - Refactored several classes to use QElapsedTimer instead of QTime for performance measurement. - Ensured all operator overloads in Section and Tag classes are marked as const for better const-correctness.
4223 lines
144 KiB
C++
4223 lines
144 KiB
C++
//! \file clippingstation.cpp
|
|
/************************************************************************
|
|
* $Id: clippingstation.cpp 668 2011-05-15 11:08:10Z elzubeir $
|
|
*
|
|
* ------------
|
|
* Description:
|
|
* ------------
|
|
*
|
|
* (C) Copyright 2009-2011 ALLCONTENT. All rights reserved.
|
|
*
|
|
* -----------------
|
|
* Revision Details: (Updated by Revision Control System)
|
|
* -----------------
|
|
* $Date: 2011-05-15 15:08:10 +0400 (Sun, 15 May 2011) $
|
|
* $Author: elzubeir $
|
|
* $Revision: 668 $
|
|
* $HeadURL: file:///opt/svn/socialhose/trunk/app/ClippingStation/clippingstation.cpp $
|
|
*
|
|
*
|
|
************************************************************************/
|
|
|
|
#include <QtGui>
|
|
#include <QtConcurrentRun>
|
|
#include <QMutex>
|
|
#include <QDesktopServices>
|
|
#include <QScreen>
|
|
#include <QRegularExpression>
|
|
|
|
#include <cstdio>
|
|
using namespace std;
|
|
|
|
|
|
#include "clippingstation.h"
|
|
#include "ui_clippingstation.h"
|
|
#include "Importer/importerdialog.h"
|
|
#include "publication.h"
|
|
#include "tag.h"
|
|
#include "pushbuttondelegate.h"
|
|
#include "tagswrapper.h"
|
|
#include "imagecutout.h"
|
|
#include "drawerview.h"
|
|
#include "systemconfiguration.h"
|
|
#include "constants.h"
|
|
#include "pagetextdialog.h"
|
|
#include "wordcoordinates.h"
|
|
#include "searchpublicationlistdialog.h"
|
|
|
|
/*
|
|
TODO: if caching has been canceled by user, or by selecting a different issue while the first one has not completed caching yet!
|
|
It should be handled, not handled yet!
|
|
|
|
*/
|
|
|
|
QMutex g_clipMutex;
|
|
|
|
QString ClippingStation::m_cacheDir;
|
|
QString ClippingStation::m_address;
|
|
QString ClippingStation::m_username;
|
|
QString ClippingStation::m_password;
|
|
int ClippingStation::m_port;
|
|
QString ClippingStation::saveClipImagesToFtpServerErrorMsg;
|
|
QImage ClippingStation::m_thumbnail;
|
|
QSqlDatabase ClippingStation::m_ocrDatabase;
|
|
QSqlDatabase ClippingStation::m_clipDatabase;
|
|
|
|
ClippingStation::ClippingStation(QWidget *parent)
|
|
: QMainWindow(parent), ui(new Ui::ClippingStation),
|
|
m_imageCachingDialog(this, m_cachedImages)
|
|
{
|
|
if ( !readSettings()) //if you cant read settings, exit
|
|
exit(0);
|
|
|
|
if( !connectToDatabase() ) //if cant connect to database, exit
|
|
exit(0);
|
|
|
|
if ( !authenticate() ) //if cant authenticate, exit
|
|
exit(0);
|
|
|
|
|
|
ui->setupUi(this); //else, create the UI
|
|
|
|
if( m_debug.compare("on", Qt::CaseInsensitive) == 0 )
|
|
{
|
|
g_logfile.open("clippingstation.log", ios::app);
|
|
g_logfile << std::string(80, '=') << std::endl;
|
|
g_debug = true;
|
|
}
|
|
else
|
|
g_debug = false;
|
|
|
|
//create the actions
|
|
createActions();
|
|
|
|
if( m_preclip.compare("on", Qt::CaseInsensitive) == 0 )
|
|
{
|
|
m_preclipContextMenu = new QMenu(this);
|
|
m_preclipContextMenu->addAction(ui->actionModifyPreclip);
|
|
m_preclipContextMenu->addSeparator();
|
|
m_preclipContextMenu->addAction(ui->actionDeletePreclip);
|
|
}
|
|
else
|
|
{
|
|
ui->preclipButton->setEnabled(false);
|
|
ui->cancelModifyPreclipButton->setEnabled(false);
|
|
}
|
|
|
|
m_clipContextMenu = new QMenu(this);
|
|
m_clipContextMenu->addAction(ui->actionViewClipText);
|
|
|
|
m_issueContextMenu = new QMenu(this);
|
|
m_issueContextMenu->addAction(ui->actionSendIssuetoORC);
|
|
|
|
m_issuePageContextMenu = new QMenu(this);
|
|
m_issuePageContextMenu->addAction(ui->actionSendPagetoORC);
|
|
m_issuePageContextMenu->addSeparator();
|
|
m_issuePageContextMenu->addAction(ui->actionViewPageText);
|
|
|
|
m_keywordsContextMenu = new QMenu(this);
|
|
m_keywordsContextMenu->addAction(ui->actionViewKeywordsSearchword);
|
|
m_keywordsContextMenu->addSeparator();
|
|
m_keywordsContextMenu->addAction(ui->actionGoToKeywordWikiPage);
|
|
|
|
|
|
m_publication.setDatabase(m_masterDatabase);
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
|
|
|
|
//populate all the publications in the publicaiton/issue drop-down list in the dock widget
|
|
QStringList list;
|
|
QSqlQuery query("SELECT id_publication, name_publication_en FROM publication", m_slaveDatabase);
|
|
while( query.next() )
|
|
{
|
|
int publicationId = query.value(0).toString().toInt();
|
|
QString publicationName = query.value(1).toString();
|
|
list << publicationName; //populate list with values from the database
|
|
|
|
m_publicationHash[publicationName] = publicationId; //also populate the hash table with name/id values
|
|
}
|
|
|
|
//load keywords from database and add them to searchPublicationdialog
|
|
QStringList keywords;
|
|
query.exec( "SELECT name_company FROM company WHERE date_end > NOW()" );
|
|
while( query.next() )
|
|
{
|
|
QString name = query.value(0).toString();
|
|
keywords.append(name);
|
|
}
|
|
|
|
query.exec("SELECT name_searchword FROM company AS cm, searchword AS sw WHERE sw.id_company = cm.id_company AND cm.date_end > NOW() ");
|
|
while( query.next() )
|
|
{
|
|
QString name = query.value(0).toString();
|
|
keywords.append(name);
|
|
}
|
|
|
|
keywords.sort();
|
|
keywords.removeDuplicates();
|
|
m_searchPublicationsDlg.setKeywords(keywords);
|
|
|
|
query.exec("SELECT id_country, name_country_en FROM country");
|
|
while( query.next() )
|
|
{
|
|
int id = query.value(0).toString().toInt();
|
|
QString name = query.value(1).toString();
|
|
|
|
m_countriesHash[name] = id; //also populate the hash table with name/id values
|
|
}
|
|
|
|
QList<QString> clist = m_countriesHash.keys();
|
|
QStringList strlist;
|
|
for(int i=0; i < clist.count(); i++)
|
|
strlist.append(clist[i]);
|
|
|
|
m_searchPublicationsDlg.setCountryList( strlist );
|
|
|
|
|
|
QCompleter* completer = new QCompleter(list, this); //createa completer with the list of publication names
|
|
completer->setCaseSensitivity(Qt::CaseInsensitive);
|
|
ui->publicationNameLineEdit_2->setCompleter(completer); //use the complete with the publicationLineEdit
|
|
|
|
// should use QDir's homePath to get the path and then use .socialhose/cache as the directory within the homePath
|
|
QDir homeDir("/home");
|
|
#if defined Q_WS_X11
|
|
m_cacheDir = homeDir.homePath() + "/.socialhose/cache/";
|
|
#elif defined Q_WS_MACX
|
|
m_cacheDir = homeDir.homePath() + "/.socialhose/cache/";
|
|
#else
|
|
m_cacheDir = QApplication::applicationDirPath();
|
|
if(!m_cacheDir.endsWith("/"))
|
|
m_cacheDir += "/";
|
|
m_cacheDir += "cache/";
|
|
#endif
|
|
|
|
ui->fullpageView->setClippingStation(this);
|
|
ui->statusBar->addProgressBarWidget(&m_imageCachingDialog);
|
|
|
|
ImporterDialog *dlg = new ImporterDialog(this, m_masterDatabase, m_slaveDatabase, m_user); //create the importer dialog
|
|
ui->importerDockWidget->setWidget(dlg); //and insert it to the importer dock widget
|
|
|
|
tabifyDockWidget(ui->importerDockWidget, ui->publicatonIssueDockWidget);
|
|
ui->importerDockWidget ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
ui->publicatonIssueDockWidget ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
ui->importerDockWidget ->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
//ui->importerDockWidget->raise();
|
|
|
|
SystemConfiguration::retreiveSystemConfiguration(m_slaveDatabase);
|
|
|
|
m_tagsWrapper.set(ui->treeView, ui->treeWidget, ui->keywordLineEdit);
|
|
|
|
ui->stackedDrawerViewWidget->removeWidget(ui->stackedDrawerViewWidget->widget(0) ); //remove the first page from the stak
|
|
|
|
m_currentA4Scale = 1.0;
|
|
|
|
drawerAddPage(true);
|
|
|
|
m_runningMode = NORMAL_MODE;
|
|
m_filterMode = NO_FILTER;
|
|
|
|
m_currentPreclipId = 0;
|
|
m_firstPageInClip = ""; //reset it
|
|
m_imageIndex = m_preclippedImageIndex = m_clippedImageIndex = 0;
|
|
m_imageModelIndex = m_preclippedImageModelIndex = m_clippedImageModelIndex = QModelIndex();
|
|
|
|
showMaximized();
|
|
|
|
ui->cancelModifyPreclipButton->setVisible(false);
|
|
|
|
//install filter to track mouse
|
|
ui->fullpageView->installEventFilter(this);
|
|
|
|
connect(&m_saveClipImagesToFtpServerWatcher, SIGNAL(finished() ), this, SLOT( saveClipImagesToFtpServerWatcherFinished() ) ); //this signal is used to upload clips to ftp server
|
|
connect(&m_saveClipImagesToFileServerWatcher, SIGNAL(finished() ), this, SLOT( saveClipImagesToFileServerWatcherFinished() ) ); //this signal is used to upload clips to ftp server
|
|
connect(&m_addTextToClipWatcher, SIGNAL(finished()), this, SLOT(addTextToClipWatcherFinished()));
|
|
|
|
//set shortcuts
|
|
setShortcuts();
|
|
|
|
connect(&m_trackingTimer, SIGNAL(timeout()), this, SLOT(updateTrackLabel()));
|
|
m_trackingTimer.setInterval(1000);
|
|
m_trackingSeconds = 0;
|
|
m_currentPageId = 0;
|
|
m_isPaused = false;
|
|
}
|
|
|
|
ClippingStation::~ClippingStation()
|
|
{
|
|
//qDebug("~ClippingStation()");
|
|
|
|
delete ui;
|
|
|
|
unlockImages();
|
|
|
|
m_trackingTimer.stop();
|
|
if(m_currentPageId > 0 && m_trackingSeconds > 0)
|
|
m_user.updateTrack(m_currentPageId, m_trackingSeconds);
|
|
|
|
m_masterDatabase.close();
|
|
m_slaveDatabase.close();
|
|
|
|
//delete all the files on the tmp directory
|
|
//QDir dir(m_cacheDir);
|
|
//recursiveDelete( dir );
|
|
//qDebug("end of ~ClippingStation()");
|
|
}
|
|
|
|
bool ClippingStation::readSettings()
|
|
{
|
|
#ifdef Q_WS_X11
|
|
QString config = "/etc/socialhose.ini";
|
|
#elif defined (Q_WS_MACX)
|
|
QString config = "/etc/socialhose.ini";
|
|
#else
|
|
QString config = QApplication::applicationDirPath()+ "/config.ini";
|
|
#endif
|
|
|
|
QSettings settings(config, QSettings::IniFormat);
|
|
|
|
m_masterDatabaseHost = settings.value("master database/server").toString(); //read master database's server value from settings
|
|
m_masterDatabaseName = settings.value("master database/database").toString(); //read master database's database name value from settings
|
|
m_masterDatabaseUser = settings.value("master database/uid").toString(); //read master database's user id value from settings
|
|
m_masterDatabasePassword = settings.value("master database/pwd").toString(); //read master database's password value from settings
|
|
m_masterDatabasePort = settings.value("master database/port").toInt(); //read master database's port value from settings
|
|
|
|
// if any string is empty return false, else return true
|
|
if(m_masterDatabaseName.isEmpty() || m_masterDatabaseHost.isEmpty() || m_masterDatabaseUser.isEmpty() ||
|
|
m_masterDatabasePassword.isEmpty() || ( m_masterDatabasePort == 0) )
|
|
{
|
|
QMessageBox::critical(this, tr("config error"), tr("Error reading 'config.ini' master database configurations\nMake sure the file exists, and its properly formatted!"));
|
|
return false;
|
|
}
|
|
|
|
|
|
m_slaveDatabaseHost = settings.value("slave database/server").toString();
|
|
m_slaveDatabaseName = settings.value("slave database/database").toString();
|
|
m_slaveDatabaseUser = settings.value("slave database/uid").toString();
|
|
m_slaveDatabasePassword = settings.value("slave database/pwd").toString();
|
|
m_slaveDatabasePort = settings.value("slave database/port").toInt();
|
|
|
|
// if any string is empty return false, else return true
|
|
if(m_slaveDatabaseName.isEmpty() || m_slaveDatabaseHost.isEmpty() || m_slaveDatabaseUser.isEmpty() ||
|
|
m_slaveDatabasePassword.isEmpty() || ( m_slaveDatabasePort == 0) )
|
|
{
|
|
QMessageBox::critical(this, tr("config error"), tr("Error reading 'config.ini' slave database configurations\nMake sure the file exists, and its properly formatted!"));
|
|
return false;
|
|
}
|
|
|
|
m_ocrDatabaseHost = settings.value("ocr database/server").toString();
|
|
m_ocrDatabaseName = settings.value("ocr database/database").toString();
|
|
m_ocrDatabaseUser = settings.value("ocr database/uid").toString();
|
|
m_ocrDatabasePassword = settings.value("ocr database/pwd").toString();
|
|
m_ocrDatabasePort = settings.value("ocr database/port").toInt();
|
|
|
|
|
|
m_useFtp = settings.value("ftp access/useftp").toInt(); //if its set to 0, its false, otherwise it true
|
|
if(m_useFtp)
|
|
{
|
|
m_address = settings.value("ftp access/server").toString();
|
|
m_username = settings.value("ftp access/username").toString();
|
|
m_password = settings.value("ftp access/password").toString();
|
|
m_port = settings.value("ftp access/port").toInt();
|
|
|
|
if(m_address.isEmpty() || m_username.isEmpty() || m_password.isEmpty() || (m_port == 0))
|
|
{
|
|
QMessageBox::critical(this, tr("config error"), tr("Error reading 'config.ini' Ftp server configurations\nMake sure the file is properly formatted!"));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//read shortcuts
|
|
m_clipShortcut = settings.value("shortcuts/Clip").toString();
|
|
m_preclipShortcut = settings.value("shortcuts/Preclip").toString();
|
|
m_addPageShortcut = settings.value("shortcuts/AddPage").toString();
|
|
m_nextPageShortcut = settings.value("shortcuts/NextPage").toString();
|
|
m_previousPageShortcut = settings.value("shortcuts/PreviousPage").toString();
|
|
|
|
m_debug = settings.value("debug mode/debug").toString();
|
|
|
|
m_preclip = settings.value("preclip mode/preclip", "on").toString();
|
|
|
|
m_maxTimeLimit = settings.value("time limit/limit").toInt();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ClippingStation::connectToDatabase()
|
|
{
|
|
// add a connection to databse based on the mysql driver, and name it master
|
|
m_masterDatabase = QSqlDatabase::addDatabase("QMYSQL", "master_123");
|
|
|
|
// initalize the connection
|
|
m_masterDatabase.setHostName(m_masterDatabaseHost);
|
|
m_masterDatabase.setPort(m_masterDatabasePort);
|
|
m_masterDatabase.setDatabaseName(m_masterDatabaseName);
|
|
m_masterDatabase.setUserName(m_masterDatabaseUser);
|
|
m_masterDatabase.setPassword(m_masterDatabasePassword);
|
|
|
|
// try to open the connection, if ok returns true, else returns false
|
|
bool ok = m_masterDatabase.open();
|
|
if(!ok)
|
|
{
|
|
// if error, get the error from the database text and print it to debug screen
|
|
QString str = m_masterDatabase.lastError().databaseText();
|
|
QMessageBox::critical(this, tr("Database Error"), tr("Error connecting to master database\n") + str);
|
|
return false;
|
|
}
|
|
|
|
// add a connection to databse based on the mysql driver, and name it slave
|
|
m_slaveDatabase = QSqlDatabase::addDatabase("QMYSQL", "slave");
|
|
|
|
// initalize the connection
|
|
m_slaveDatabase.setHostName(m_slaveDatabaseHost);
|
|
m_slaveDatabase.setPort(m_slaveDatabasePort);
|
|
m_slaveDatabase.setDatabaseName(m_slaveDatabaseName);
|
|
m_slaveDatabase.setUserName(m_slaveDatabaseUser);
|
|
m_slaveDatabase.setPassword(m_slaveDatabasePassword);
|
|
|
|
// try to open the connection, if ok returns true, else returns false
|
|
ok = m_slaveDatabase.open();
|
|
if(!ok)
|
|
{
|
|
// if error, get the error from the database text and print it to debug screen
|
|
QString str = m_slaveDatabase.lastError().databaseText();
|
|
QMessageBox::critical(this, tr("Database Error"), tr("Error connecting to slave database\n") + str);
|
|
return false;
|
|
}
|
|
|
|
|
|
m_ocrDatabase = QSqlDatabase::addDatabase("QMYSQL", "ocr");
|
|
|
|
// initalize the connection
|
|
m_ocrDatabase.setHostName(m_ocrDatabaseHost);
|
|
m_ocrDatabase.setPort(m_ocrDatabasePort);
|
|
m_ocrDatabase.setDatabaseName(m_ocrDatabaseName);
|
|
m_ocrDatabase.setUserName(m_ocrDatabaseUser);
|
|
m_ocrDatabase.setPassword(m_ocrDatabasePassword);
|
|
|
|
// try to open the connection, if ok returns true, else returns false
|
|
ok = m_ocrDatabase.open();
|
|
if(!ok)
|
|
{
|
|
// if error, get the error from the database text and print it to debug screen
|
|
QString str = m_ocrDatabase.lastError().databaseText();
|
|
QMessageBox::critical(this, tr("Database Error"), tr("Error connecting to ocr database\n") + str);
|
|
return false;
|
|
}
|
|
|
|
m_clipDatabase = m_masterDatabase.cloneDatabase(m_masterDatabase, "clip");
|
|
m_clipDatabase.open();
|
|
|
|
if(!m_clipDatabase.isOpen())
|
|
{
|
|
QString str = m_clipDatabase.lastError().text();
|
|
QMessageBox::critical(this, tr("Database Error"), tr("Error opening clip database\n") + str);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ClippingStation::authenticate()
|
|
{
|
|
//after opening the database connection, we pass it to the user object
|
|
m_user.setSlaveDatabase(m_slaveDatabase);
|
|
m_user.setMasterDatabase(m_masterDatabase);
|
|
|
|
return m_user.authenticate();
|
|
}
|
|
|
|
|
|
void ClippingStation::createActions()
|
|
{
|
|
//create actions for the main window
|
|
connect(ui->actionImporter, SIGNAL(triggered()), this, SLOT(onActionImporter()));
|
|
connect(ui->action_Exit, SIGNAL(triggered()), this, SLOT(close()));
|
|
connect(ui->actionKeyword, SIGNAL(triggered()), this, SLOT(onActionKeyword()));
|
|
connect(ui->actionPublications, SIGNAL(triggered()), this, SLOT(onActionPublications()));
|
|
|
|
connect(ui->actionClip, SIGNAL(triggered()), this, SLOT(onActionClip()));
|
|
|
|
if( m_preclip.compare("on", Qt::CaseInsensitive) == 0 )
|
|
{
|
|
connect(ui->actionPreclip, SIGNAL(triggered()), this, SLOT(onActionPreclip()));
|
|
connect(ui->actionModifyPreclip, SIGNAL(triggered()), this, SLOT(onActionModifyePreclip()));
|
|
connect(ui->actionDeletePreclip, SIGNAL(triggered()), this, SLOT(onActionDeletePreclip()));
|
|
}
|
|
//drawer actions
|
|
connect(ui->actionDrawerAddPage, SIGNAL(triggered()), this, SLOT(drawerAddPage()));
|
|
connect(ui->actionDrawerRemovePage, SIGNAL(triggered()), this, SLOT(drawerRemovePage()));
|
|
|
|
//page navigation actions
|
|
connect(ui->actionFirstPage, SIGNAL(triggered()), this, SLOT(firstPage()));
|
|
connect(ui->actionPreviousPage, SIGNAL(triggered()), this, SLOT(previousPage()));
|
|
connect(ui->actionNextPage, SIGNAL(triggered()), this, SLOT(nextPage()));
|
|
connect(ui->actionLastPage, SIGNAL(triggered()), this, SLOT(lastPage()));
|
|
|
|
//zoom in/out
|
|
connect(ui->actionZoomIn, SIGNAL(triggered()), this, SLOT(zoomIn()));
|
|
connect(ui->actionZoomOut, SIGNAL(triggered()), this, SLOT(zoomOut()));
|
|
|
|
//auto-arrange
|
|
connect(ui->actionAutoArrange, SIGNAL(triggered()), this, SLOT(onActionAutoArrange()));
|
|
|
|
connect(ui->actionMarkIssueAsDone, SIGNAL(triggered()), this, SLOT(onActionMarkIssueAsDone()));
|
|
connect(ui->actionMarkIssueAsUndone,SIGNAL(triggered()), this, SLOT(onActionMarkIssueAsUndone()));
|
|
connect(ui->actionSendIssuetoORC, SIGNAL(triggered()), this, SLOT(onActionSendIssueToOCR()));
|
|
connect(ui->actionSendPagetoORC, SIGNAL(triggered()), this, SLOT(onActionSendPageToOCR()));
|
|
connect(ui->actionViewPageText, SIGNAL(triggered()), this, SLOT(onActionViewPageText()));
|
|
|
|
connect(ui->actionViewClipText, SIGNAL(triggered()), this, SLOT(onActionViewClipText()));
|
|
|
|
connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(onActionAbout()));
|
|
|
|
connect(ui->actionViewKeywordsSearchword, SIGNAL(triggered()), this, SLOT(onActionViewKeywordsSearchword()));
|
|
connect(ui->actionGoToKeywordWikiPage , SIGNAL(triggered()), this, SLOT(onActionGoToKeywordWikiPage()));
|
|
}
|
|
|
|
void ClippingStation::onActionImporter()
|
|
{
|
|
ui->importerDockWidget->setVisible(ui->actionImporter->isChecked());
|
|
}
|
|
|
|
void ClippingStation::onActionKeyword()
|
|
{
|
|
ui->keywordDockWidget->setVisible(ui->actionKeyword->isChecked());
|
|
}
|
|
|
|
void ClippingStation::onActionPublications()
|
|
{
|
|
ui->publicatonIssueDockWidget->setVisible(ui->actionPublications->isChecked());
|
|
}
|
|
|
|
void ClippingStation::onActionClip()
|
|
{
|
|
clip();
|
|
}
|
|
|
|
void ClippingStation::onActionPreclip()
|
|
{
|
|
preclip();
|
|
}
|
|
|
|
|
|
void ClippingStation::onActionModifyePreclip()
|
|
{
|
|
QModelIndexList list = ui->clipsTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
|
|
articleTreeViewClicked(index);
|
|
setModifyPreclipButton(true);
|
|
}
|
|
|
|
|
|
void ClippingStation::onActionDeletePreclip()
|
|
{
|
|
QModelIndexList list = ui->clipsTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
if(index.isValid())
|
|
{
|
|
//check index to the value
|
|
QAbstractItemModel *model = ui->clipsTreeView->model();
|
|
|
|
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
|
|
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
|
|
//if the user clicked on top level entries, just return
|
|
if ( index == preclipRootIndex ||
|
|
index == clipRootIndex )
|
|
return;
|
|
|
|
int id;
|
|
if ( index.parent() == preclipRootIndex ||
|
|
index.parent().parent() == preclipRootIndex )
|
|
{
|
|
m_runningMode = PRECLIPPING_MODE;
|
|
QModelIndex currentIndex;
|
|
|
|
m_clippedImageModelIndex = QModelIndex();
|
|
|
|
|
|
//if the selection is the Preclip(), then it will contain the id
|
|
if(index.parent() == preclipRootIndex)
|
|
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
|
|
else
|
|
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
|
|
|
|
switch( QMessageBox::question(
|
|
this,
|
|
tr("Delete Preclip"),
|
|
tr("This will delete the preclip PERMANENTLY, Are you sure?"),
|
|
QMessageBox::Yes |
|
|
QMessageBox::No,
|
|
QMessageBox::No) )
|
|
{
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
m_publication.currentIssue()->preclip(id).deleteArticle(m_masterDatabase);
|
|
m_publication.currentIssue()->deleteArticleFromView(ui->clipsTreeView, id);
|
|
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
|
|
|
|
//m_publication.currentIssue()->loadArticles(m_slaveDatabase, m_filterMode);
|
|
//m_publication.currentIssue()->showArticles(ui->clipsTreeView);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
void ClippingStation::onActionAutoArrange()
|
|
{
|
|
QList<ImageCutout*> cutouts = ui->fullpageView->imageCutoutsList();
|
|
if(cutouts.count() <= 0)
|
|
return;
|
|
|
|
orderList(cutouts);
|
|
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget() );
|
|
QSizeF cellSize = A4CellSize(true);
|
|
bool isfirstPage = true;
|
|
|
|
bool resetArray = true;
|
|
for(int i=0; i< cutouts.count(); i++)
|
|
{
|
|
QString currentImage;
|
|
|
|
if(m_runningMode == NORMAL_MODE)
|
|
currentImage = m_localImagesList[m_imageIndex];
|
|
else if(m_runningMode == PRECLIPPING_MODE)
|
|
currentImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
|
|
else if(m_runningMode == CLIPPING_MODE)
|
|
currentImage = m_clippedLocalImagesList[m_clippedImageIndex];
|
|
|
|
if(cutouts[i]->pageName() != currentImage)
|
|
{
|
|
if(m_runningMode == NORMAL_MODE)
|
|
{
|
|
int index = m_localImagesList.indexOf(cutouts[i]->pageName());
|
|
if(index < 0)
|
|
return;
|
|
m_imageIndex = index;
|
|
}
|
|
else if(m_runningMode == PRECLIPPING_MODE)
|
|
{
|
|
int index = m_preclippedLocalImagesList.indexOf(cutouts[i]->pageName());
|
|
if(index < 0)
|
|
return;
|
|
m_preclippedImageIndex = index;
|
|
}
|
|
else if(m_runningMode == CLIPPING_MODE)
|
|
{
|
|
int index = m_clippedLocalImagesList.indexOf(cutouts[i]->pageName());
|
|
if(index < 0)
|
|
return;
|
|
m_clippedImageIndex = index;
|
|
}
|
|
|
|
loadImage();
|
|
}
|
|
|
|
QImage img = cutouts[i]->createCutout();
|
|
int type = cutouts[i]->areaType();
|
|
QPointF pos;
|
|
qreal scale = 1.0;
|
|
if(calculatePosAndScale(cellSize, img, type, resetArray, pos, scale))
|
|
{
|
|
addMargintoPos(pos, isfirstPage);
|
|
view->addCutout(img, pos, scale);
|
|
}
|
|
else
|
|
{
|
|
isfirstPage = false;
|
|
drawerAddPage(isfirstPage);
|
|
drawerNextPage();
|
|
view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget() );
|
|
cellSize = A4CellSize(isfirstPage);
|
|
|
|
if(calculatePosAndScale(cellSize, img, type, true, pos, scale))
|
|
{
|
|
addMargintoPos(pos, isfirstPage);
|
|
view->addCutout(img, pos, scale);
|
|
}
|
|
else
|
|
{
|
|
//error, the cutout is larger than the avaialble space in the A4 page
|
|
ui->stackedDrawerViewWidget->removeWidget( ui->stackedDrawerViewWidget->currentWidget() );
|
|
updateDrawerPageInformation();
|
|
QMessageBox::information(this, tr("Large Cutout"), tr("Cutout number %1 does not fit in the available space").arg(i+1));
|
|
return;
|
|
}
|
|
}
|
|
resetArray = false;
|
|
}
|
|
//iterate thru all the views, and center the images
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(i);
|
|
view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
bool isArabic = (m_publication.language() == "Arabic");
|
|
view->centerCutouts(isArabic);
|
|
}
|
|
|
|
//return to the first page to create the thumbnail
|
|
QString currentImage;
|
|
|
|
if(m_runningMode == NORMAL_MODE)
|
|
currentImage = m_localImagesList[m_imageIndex];
|
|
else if(m_runningMode == PRECLIPPING_MODE)
|
|
currentImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
|
|
else if(m_runningMode == CLIPPING_MODE)
|
|
currentImage = m_clippedLocalImagesList[m_clippedImageIndex];
|
|
|
|
if(cutouts[0]->pageName() != currentImage)
|
|
{
|
|
if(m_runningMode == NORMAL_MODE)
|
|
{
|
|
int index = m_localImagesList.indexOf(cutouts[0]->pageName());
|
|
if(index < 0)
|
|
return;
|
|
m_imageIndex = index;
|
|
}
|
|
else if(m_runningMode == PRECLIPPING_MODE)
|
|
{
|
|
int index = m_preclippedLocalImagesList.indexOf(cutouts[0]->pageName());
|
|
if(index < 0)
|
|
return;
|
|
m_preclippedImageIndex = index;
|
|
}
|
|
else if(m_runningMode == CLIPPING_MODE)
|
|
{
|
|
int index = m_clippedLocalImagesList.indexOf(cutouts[0]->pageName());
|
|
if(index < 0)
|
|
return;
|
|
m_clippedImageIndex = index;
|
|
}
|
|
|
|
loadImage();
|
|
}
|
|
|
|
createThumbnail();
|
|
}
|
|
|
|
|
|
void ClippingStation::onActionMarkIssueAsDone()
|
|
{
|
|
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
//QString date =
|
|
|
|
if( !index.isValid() )
|
|
return;
|
|
|
|
switch( QMessageBox::question(
|
|
this,
|
|
tr("Mark Issue as Done"),
|
|
tr("This will mark the current issue as Done\nAre you sure?"),
|
|
QMessageBox::Yes |
|
|
QMessageBox::No,
|
|
QMessageBox::No) )
|
|
{
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
if(model->parent(index) == QModelIndex() ) index = index;
|
|
else if(model->parent(index).parent() == QModelIndex() ) index = index.parent();
|
|
else if(model->parent(index).parent().parent() == QModelIndex() ) index = index.parent().parent();
|
|
else index = index.parent().parent().parent();
|
|
|
|
QString date = model->data(index, Qt::DisplayRole).toString();
|
|
|
|
m_publication.issue(date)->markIssueAsDone(m_masterDatabase, true, m_user.id());
|
|
model->setData(index, QVariant(QIcon(":/icons/ok.png")) , Qt::DecorationRole);
|
|
}
|
|
|
|
void ClippingStation::onActionMarkIssueAsUndone()
|
|
{
|
|
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
//QString date =
|
|
|
|
if( !index.isValid() )
|
|
return;
|
|
|
|
switch( QMessageBox::question(
|
|
this,
|
|
tr("Mark Issue as Undone"),
|
|
tr("This will mark the current issue as Undone\nAre you sure?"),
|
|
QMessageBox::Yes |
|
|
QMessageBox::No,
|
|
QMessageBox::No) )
|
|
{
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
if(model->parent(index) == QModelIndex() ) index = index;
|
|
else if(model->parent(index).parent() == QModelIndex() ) index = index.parent();
|
|
else if(model->parent(index).parent().parent() == QModelIndex() ) index = index.parent().parent();
|
|
else index = index.parent().parent().parent();
|
|
|
|
QString date = model->data(index, Qt::DisplayRole).toString();
|
|
|
|
m_publication.issue(date)->markIssueAsDone(m_masterDatabase, false, m_user.id());
|
|
model->setData(index, QVariant(QIcon(":/icons/cancel.png")) , Qt::DecorationRole);
|
|
}
|
|
|
|
|
|
void ClippingStation::onActionSendPageToOCR()
|
|
{
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
|
|
QString pageName = index .data(Qt::DisplayRole).toString();
|
|
//convert pageName from Page # to ####.jpg
|
|
pageName = QString("%1.jpg").arg(pageName.remove(QRegularExpression("[^\\d]")), 4, QChar('0'));
|
|
|
|
QString sectionName = model->parent(index) .data(Qt::DisplayRole).toString();
|
|
QString issueDate = model->parent(index).parent().data(Qt::DisplayRole).toString();
|
|
|
|
//send the page to OCR to be processed again
|
|
QSqlQuery query(m_slaveDatabase);
|
|
query.prepare("SELECT id_publication_issue FROM publication_issue "
|
|
"WHERE id_publication = :id_publication AND id_issue = :id_issue AND issue_date = :issue_date");
|
|
|
|
query.bindValue(":id_publication", m_publication.id() );
|
|
query.bindValue(":id_issue", m_publication.issue(issueDate)->id() );
|
|
query.bindValue(":issue_date", issueDate);
|
|
|
|
if(!query.exec())
|
|
{
|
|
//error happened
|
|
return;
|
|
}
|
|
|
|
int id_publication_issue = 0;
|
|
|
|
if(query.next())
|
|
{
|
|
id_publication_issue = query.value(0).toInt();
|
|
//return id_publication_issue;
|
|
//break;
|
|
}
|
|
|
|
|
|
query.prepare("SELECT id_issue_sections FROM issue_sections WHERE "
|
|
"id_publication_issue = :id_publication_issue AND id_section = :id_section");
|
|
query.bindValue(":id_publication_issue", id_publication_issue);
|
|
query.bindValue(":id_section", m_publication.issue(issueDate)->section(sectionName).id() );
|
|
|
|
if ( !query.exec() )
|
|
return;
|
|
|
|
int id_issue_sections = 0;
|
|
if( query.next() )
|
|
{
|
|
id_issue_sections = query.value(0).toInt();
|
|
//break;
|
|
}
|
|
|
|
//we have the page name, and the id_issue_sections, we can now reset the pages to OCR
|
|
|
|
|
|
//query.exec("LOCK TABLES section_pages WRITE, page_text WRITE, page_tag_coordinates WRITE;"); //query.exec("LOCK TABLES section_pages");
|
|
|
|
//first remove the pre processed values
|
|
query.prepare("SELECT section_pages FROM section_pages "
|
|
"WHERE "
|
|
" id_issue_sections = :id_issue_sections "
|
|
" AND page_name like :page_name");
|
|
|
|
query.bindValue(":id_issue_sections" , id_issue_sections);
|
|
query.bindValue(":page_name", pageName);
|
|
|
|
if (query.exec() )
|
|
{
|
|
int id = 0;
|
|
if(query.next())
|
|
id = query.value(0).toInt();
|
|
|
|
//delete the previous coordinates
|
|
query.prepare("DELETE FROM page_tag_coordinates WHERE id_section_pages = :id");
|
|
query.bindValue(":id", id);
|
|
query.exec();
|
|
|
|
query.prepare("DELETE FROM page_text WHERE id_section_pages = :id");
|
|
query.bindValue(":id", id);
|
|
query.exec();
|
|
}
|
|
|
|
query.prepare("UPDATE section_pages SET status = 1 "
|
|
"WHERE "
|
|
" section_pages.id_issue_sections = :id_issue_sections "
|
|
" AND section_pages.page_name like :page_name AND status != 1");
|
|
|
|
query.bindValue(":id_issue_sections" , id_issue_sections);
|
|
query.bindValue(":page_name", pageName);
|
|
|
|
query.exec();
|
|
|
|
//query.exec("UNLOCK TABLES");
|
|
|
|
model->setData(index, QVariant(QIcon(":/icons/gray_circle.png")) , Qt::DecorationRole);
|
|
|
|
//loadImage(); //no need to re-load the page because it may not by the page that the user is currently looking at
|
|
}
|
|
|
|
void ClippingStation::onActionSendIssueToOCR()
|
|
{
|
|
switch( QMessageBox::question(
|
|
this,
|
|
tr("Send issue back to OCR"),
|
|
tr("This operation will send the entire issue back to OCR\nAre you sure?"),
|
|
QMessageBox::Yes |
|
|
QMessageBox::No,
|
|
QMessageBox::No) )
|
|
{
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex issueIndex = list[0];
|
|
QString issueDate = model->data(issueIndex, Qt::DisplayRole).toString();
|
|
|
|
//send the entire issue to OCR to be processed again
|
|
QSqlQuery query(m_slaveDatabase);
|
|
|
|
query.exec("LOCK TABLES section_pages WRITE, issue_sections READ , publication_issue READ;");
|
|
|
|
//first remove the pre processed values
|
|
query.prepare("UPDATE section_pages, issue_sections, publication_issue "
|
|
" SET status = 1 "
|
|
" WHERE section_pages.id_issue_sections = issue_sections.id_issue_sections "
|
|
" AND issue_sections.id_publication_issue = publication_issue.id_publication_issue "
|
|
" AND id_issue = :id_issue AND publication_issue.id_publication = :id_publication;");
|
|
|
|
query.bindValue(":id_issue" , m_publication.issue(issueDate)->id() );
|
|
query.bindValue(":id_publication", m_publication.id() );
|
|
|
|
if ( !query.exec() )
|
|
{
|
|
query.exec("UNLOCK TABLES");
|
|
return;
|
|
}
|
|
|
|
query.exec("UNLOCK TABLES");
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
int sectionsCount = model->rowCount(issueIndex);
|
|
|
|
for(int j=0; j < sectionsCount; j++)
|
|
{
|
|
QString sectionName = model->index(j, 0, issueIndex).data(Qt::DisplayRole).toString();
|
|
QModelIndex sectionIndex = model->index(j, 0, issueIndex);
|
|
int pagesCount = model->rowCount(sectionIndex);
|
|
|
|
for(int k=0; k< pagesCount; k++)
|
|
{
|
|
QModelIndex pageIndex = model->index(k, 0, sectionIndex);
|
|
model->setData(pageIndex, QVariant(QIcon(":/icons/gray_circle.png")) , Qt::DecorationRole);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClippingStation::onActionViewClipText()
|
|
{
|
|
QAbstractItemModel *model = ui->clipsTreeView->model();
|
|
|
|
QModelIndexList list = ui->clipsTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
|
|
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
|
|
//if the user clicked on top level entries, just return
|
|
|
|
int id;
|
|
if ( index.parent() == clipRootIndex ||
|
|
index.parent().parent() == clipRootIndex )
|
|
{
|
|
//m_clippedImageModelIndex = QModelIndex();
|
|
if(index.parent() == clipRootIndex)
|
|
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
|
|
else
|
|
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
|
|
|
|
//get the text_ocr.
|
|
QSqlQuery query(m_masterDatabase);
|
|
query.prepare("SELECT `text_ocr` FROM article WHERE id_article = :id");
|
|
query.bindValue(":id", id);
|
|
if ( !query.exec() )
|
|
return;
|
|
|
|
QString text;
|
|
|
|
while(query.next())
|
|
text = query.value(0).toString();
|
|
|
|
PageTextDialog dlg(this, text);
|
|
dlg.exec();
|
|
}
|
|
}
|
|
|
|
void ClippingStation::onActionViewPageText()
|
|
{
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
QModelIndexList list = ui->issuesTreeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
|
|
QString pageName = index .data(Qt::DisplayRole).toString();
|
|
pageName = QString("%1.jpg").arg(pageName.remove(QRegularExpression("[^\\d]")), 4, QChar('0'));
|
|
|
|
QString sectionName = model->parent(index) .data(Qt::DisplayRole).toString();
|
|
QString issueDate = model->parent(index).parent().data(Qt::DisplayRole).toString();
|
|
|
|
QSqlQuery query(m_slaveDatabase);
|
|
query.prepare("SELECT id_publication_issue FROM publication_issue "
|
|
"WHERE id_publication = :id_publication AND id_issue = :id_issue AND issue_date = :issue_date");
|
|
|
|
query.bindValue(":id_publication", m_publication.id() );
|
|
query.bindValue(":id_issue", m_publication.issue(issueDate)->id() );
|
|
query.bindValue(":issue_date", issueDate);
|
|
|
|
if(!query.exec())
|
|
{
|
|
//error happened
|
|
return;
|
|
}
|
|
|
|
int id_publication_issue = 0;
|
|
|
|
if(query.next())
|
|
id_publication_issue = query.value(0).toInt();
|
|
|
|
|
|
query.prepare("SELECT id_issue_sections FROM issue_sections WHERE "
|
|
"id_publication_issue = :id_publication_issue AND id_section = :id_section");
|
|
query.bindValue(":id_publication_issue", id_publication_issue);
|
|
query.bindValue(":id_section", m_publication.issue(issueDate)->section(sectionName).id() );
|
|
|
|
if ( !query.exec() )
|
|
return;
|
|
|
|
int id_issue_sections = 0;
|
|
if( query.next() )
|
|
id_issue_sections = query.value(0).toInt();
|
|
|
|
query.exec("LOCK TABLES section_pages READ");
|
|
|
|
query.prepare("SELECT section_pages FROM section_pages "
|
|
"WHERE "
|
|
" section_pages.id_issue_sections = :id_issue_sections "
|
|
" AND section_pages.page_name like :page_name");
|
|
|
|
query.bindValue(":id_issue_sections" , id_issue_sections);
|
|
query.bindValue(":page_name", pageName);
|
|
|
|
if ( !query.exec() )
|
|
{
|
|
query.exec("UNLOCK TABLES");
|
|
return;
|
|
}
|
|
|
|
int id = 0;
|
|
while(query.next())
|
|
id = query.value(0).toInt();
|
|
|
|
query.exec("UNLOCK TABLES");
|
|
|
|
|
|
query.prepare("SELECT `text` FROM page_text WHERE id_section_pages = :id");
|
|
query.bindValue(":id", id);
|
|
if ( !query.exec() )
|
|
return;
|
|
|
|
QString text;
|
|
|
|
while(query.next())
|
|
text = query.value(0).toString();
|
|
|
|
PageTextDialog dlg(this, text);
|
|
dlg.exec();
|
|
|
|
}
|
|
|
|
|
|
void ClippingStation::onActionViewKeywordsSearchword()
|
|
{
|
|
// QAbstractItemModel *model = ui->treeView->model();
|
|
|
|
QModelIndexList list = ui->treeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
|
|
QString pageName = index .data(Qt::DisplayRole).toString();
|
|
|
|
|
|
//get searchwords for this keywords
|
|
QString lstring = Tag::loadSearchwords(m_slaveDatabase, pageName);
|
|
QMessageBox::information(0, "Searchwords", QString("Searchwords are:\n%1").arg(lstring));
|
|
|
|
}
|
|
|
|
void ClippingStation::onActionGoToKeywordWikiPage()
|
|
{
|
|
// QAbstractItemModel *model = ui->treeView->model();
|
|
|
|
QModelIndexList list = ui->treeView->selectionModel()->selectedIndexes();
|
|
if (list.count() == 0)
|
|
return;
|
|
|
|
QModelIndex index = list[0];
|
|
|
|
QString keyword = index.data(Qt::DisplayRole).toString();
|
|
|
|
keyword.replace(QRegularExpression("\\s"), "_");
|
|
keyword.replace(' ', '_');
|
|
// keyword.replace("'", "_");
|
|
// keyword.replace("-", "_");
|
|
|
|
QUrl url(QString("%1%2").arg(SystemConfiguration::wikiUrl()).arg(keyword));
|
|
// QMessageBox::information(this, "test", QString("URL is %1").arg(url.toString()));
|
|
|
|
QDesktopServices::openUrl (url);
|
|
}
|
|
|
|
void ClippingStation::onActionAbout()
|
|
{
|
|
QMessageBox::about(this, tr("About Clipping Station"),
|
|
"<html><body><p style=""color: #696969""><b>Clipping Station</b> - $Revision: 668 $</p>"
|
|
"<p style=""color: #696969"">(c) Copyright 2009-2011 ALLCONTENT. All rights reserved.</p></body></html>");
|
|
}
|
|
|
|
|
|
bool ClippingStation::eventFilter(QObject *obj, QEvent *event)
|
|
{
|
|
if (obj == ui->treeWidget)
|
|
{
|
|
if(event->type() == QEvent::KeyPress)
|
|
{
|
|
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
|
|
if(keyEvent->key() == Qt::Key_Enter)
|
|
{
|
|
selectKeyword();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return QMainWindow::eventFilter(obj, event);
|
|
}
|
|
|
|
|
|
|
|
void ClippingStation::loadIssues()
|
|
{
|
|
QString name = ui->publicationNameLineEdit_2->text();
|
|
int id = m_publicationHash[name];
|
|
|
|
m_publication.setId(id);
|
|
m_publication.setName(name);
|
|
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
//m_publication.loadIssues(ui->issuesTreeView, m_cacheDir);
|
|
m_publication.loadIssuesOnly(ui->issuesTreeView);
|
|
//m_publication.addImageCutoutsToIssues(ui->issuesTreeView, true);
|
|
|
|
m_currentIssueDate = "";
|
|
m_currentSectionName="";
|
|
}
|
|
|
|
void ClippingStation::loadIssuesWithPreclipsOnly()
|
|
{
|
|
clock_t start = clock();
|
|
|
|
QString name = ui->preclippedPublicationComboBox->currentText();
|
|
|
|
if ( name.isEmpty() )
|
|
return;
|
|
|
|
int id = m_publicationHash[name];
|
|
|
|
m_publication.setId(id);
|
|
m_publication.setName(name);
|
|
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
m_publication.loadIssuesWithPreclipsOnly(ui->issuesTreeView, m_cacheDir);
|
|
|
|
m_currentIssueDate = "";
|
|
m_currentSectionName="";
|
|
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
QModelIndex issuesIndex = model->index(0, 0, QModelIndex() );
|
|
if( issuesIndex.isValid() )
|
|
{
|
|
issueTreeViewItemClicked(issuesIndex);
|
|
//load the first pre-clip
|
|
QAbstractItemModel *model = ui->clipsTreeView->model();
|
|
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
|
|
QModelIndex pindex = model->index(0, 0, preclipRootIndex);
|
|
if(pindex.isValid())
|
|
articleTreeViewClicked(pindex);
|
|
}
|
|
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
qDebug("loadIssuesWithPreclipsOnly() Time: %f", diff);
|
|
|
|
}
|
|
|
|
void ClippingStation::loadFilteredIssues()
|
|
{
|
|
clock_t start = clock();
|
|
|
|
QString name = ui->filteredPublicationComboBox->currentText();
|
|
|
|
if ( name.isEmpty() )
|
|
return;
|
|
|
|
int id = m_publicationHash[name];
|
|
|
|
m_publication.setId(id);
|
|
m_publication.setName(name);
|
|
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
|
|
QString keyword, startDate, endDate, type, country, ocrSearchword, status;
|
|
bool ischecked;
|
|
m_searchPublicationsDlg.get(keyword, ischecked, startDate, endDate, type, country, ocrSearchword, status);
|
|
|
|
//now search for the publications that meet those criteria
|
|
int countryId = -1;
|
|
if(!country.isEmpty())
|
|
countryId = m_countriesHash[country];
|
|
|
|
int typeId = -1;
|
|
if(!type.isEmpty())
|
|
{
|
|
if(type.compare("newspaper", Qt::CaseInsensitive) == 0) //NEWSPAPER 1
|
|
typeId = 1;
|
|
else if(type.compare("magazine", Qt::CaseInsensitive) == 0)
|
|
typeId = 2;
|
|
}
|
|
|
|
m_publication.loadFilteredIssues(ui->issuesTreeView, m_ocrDatabase, m_cacheDir, startDate, endDate, keyword, ocrSearchword, status);
|
|
|
|
m_currentIssueDate = "";
|
|
m_currentSectionName="";
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
qDebug("loadIssuesWithPreclipsOnly() Time: %f", diff);
|
|
}
|
|
|
|
void ClippingStation::loadUndoneIssuesOnly()
|
|
{
|
|
clock_t start = clock();
|
|
|
|
QString name = ui->undonePublicationComboBox->currentText();
|
|
|
|
if ( name.isEmpty() )
|
|
return;
|
|
|
|
int id = m_publicationHash[name];
|
|
|
|
m_publication.setId(id);
|
|
m_publication.setName(name);
|
|
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
m_publication.loadUndoneIssuesOnly(ui->issuesTreeView);
|
|
|
|
m_currentIssueDate = "";
|
|
m_currentSectionName="";
|
|
/*
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
QModelIndex issuesIndex = model->index(0, 0, QModelIndex() );
|
|
if( issuesIndex.isValid() )
|
|
{
|
|
issueTreeViewItemClicked(issuesIndex);
|
|
//load the first pre-clip
|
|
QAbstractItemModel *model = ui->clipsTreeView->model();
|
|
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
|
|
QModelIndex pindex = model->index(0, 0, preclipRootIndex);
|
|
if(pindex.isValid())
|
|
articleTreeViewClicked(pindex);
|
|
}
|
|
|
|
*/
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
qDebug("loadUndoneIssuesOnly() Time: %f", diff);
|
|
}
|
|
|
|
void ClippingStation::issueTreeViewItemClicked(QModelIndex index)
|
|
{
|
|
qDebug("issueTreeViewItemClicked()");
|
|
if( index.isValid() )
|
|
{
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
if(model->parent(index) == QModelIndex() )
|
|
{
|
|
//qDebug("We are at Issue Level");
|
|
//we may have not loaded the sections, so we do that, and then do our work
|
|
//
|
|
QString issueDate = model->data(index , Qt::DisplayRole).toString();
|
|
if( !m_publication.issue(issueDate)->isLoaded() )
|
|
{
|
|
//load the issue, and
|
|
QStandardItemModel *standardModel = static_cast<QStandardItemModel*> ( ui->issuesTreeView->model() );
|
|
QStandardItem* issueItem = standardModel->itemFromIndex(index);
|
|
m_publication.loadIssueSections(issueItem, issueDate, m_cacheDir);
|
|
}
|
|
|
|
QString sectionName = model->data(model->index(0, 0, index), Qt::DisplayRole).toString();
|
|
|
|
if( m_currentIssueDate != issueDate)
|
|
ui->fullpageView->removeImageCutouts();
|
|
|
|
m_currentIssueDate = issueDate;
|
|
m_publication.setCurrentIssue(issueDate);
|
|
m_publication.currentIssue()->showArticlesInView(m_masterDatabase, ui->clipsTreeView, m_filterMode);
|
|
m_publication.currentIssue()->section(sectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
|
|
|
|
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
|
|
|
|
ui->issuesTreeView->expand(index);
|
|
updateSectionPagesStatus();
|
|
return;
|
|
}
|
|
|
|
if(model->parent(index).parent() == QModelIndex() )
|
|
{
|
|
//qDebug("We are at Section Level");
|
|
QString issueDate = model->data(index.parent(), Qt::DisplayRole).toString();
|
|
QString sectionName = model->data(index , Qt::DisplayRole).toString();
|
|
|
|
if( m_currentIssueDate != issueDate)
|
|
ui->fullpageView->removeImageCutouts();
|
|
|
|
m_currentIssueDate = issueDate;
|
|
m_publication.setCurrentIssue(issueDate);
|
|
m_publication.currentIssue()->showArticlesInView(m_masterDatabase, ui->clipsTreeView, m_filterMode);
|
|
m_publication.currentIssue()->section(sectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
|
|
|
|
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
|
|
|
|
ui->issuesTreeView->expand(index);
|
|
updateSectionPagesStatus();
|
|
return;
|
|
}
|
|
|
|
bool showArticleSelections;
|
|
int articleId = 0;
|
|
|
|
if(model->parent(index).parent().parent() == QModelIndex() ) //its the image
|
|
showArticleSelections = false;
|
|
else //its a selection in the image
|
|
{
|
|
showArticleSelections = true;
|
|
articleId = index.data(Qt::DisplayRole).toInt();
|
|
index = index.parent();
|
|
//gotoArticlePage(articleId);
|
|
}
|
|
|
|
|
|
QString sectionName = model->parent(index) .data(Qt::DisplayRole).toString();
|
|
QString issueDate = model->parent(index).parent().data(Qt::DisplayRole).toString();
|
|
|
|
if( m_currentIssueDate != issueDate)
|
|
{
|
|
ui->fullpageView->removeImageCutouts();
|
|
updateSectionPagesStatus();
|
|
}
|
|
else if(m_currentSectionName != sectionName)
|
|
ui->fullpageView->hideImageCutouts();
|
|
|
|
|
|
m_currentIssueDate = issueDate;
|
|
m_currentSectionName = sectionName;
|
|
|
|
m_publication.setCurrentIssue(issueDate);
|
|
m_publication.currentIssue()->showArticlesInView(m_masterDatabase, ui->clipsTreeView, m_filterMode);
|
|
m_publication.currentIssue()->section(sectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
|
|
|
|
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
|
|
|
|
if(m_runningMode != NORMAL_MODE && ui->preclipButton->text() == tr("Preclip") )
|
|
{
|
|
ui->fullpageView->removeImageCutouts();
|
|
|
|
m_tagsWrapper.clearTags();
|
|
m_tagsWrapper.showModel();
|
|
|
|
if(m_runningMode == CLIPPING_MODE)
|
|
drawerResetPages();
|
|
}
|
|
|
|
if ( ui->fullpageView->preselectedImageCutoutsCount() > 0 )
|
|
{
|
|
ui->fullpageView->removePreselectedImageCutouts();
|
|
m_tagsWrapper.clearTags();
|
|
m_tagsWrapper.showModel();
|
|
}
|
|
|
|
if(showArticleSelections)
|
|
{
|
|
ui->fullpageView->setPreselectedImageCutouts( m_publication.currentIssue()->getImageCutouts(articleId) );
|
|
|
|
m_tagsWrapper.setOcrTags(m_publication.currentIssue()->articleTags(articleId));
|
|
m_tagsWrapper.showModel();
|
|
}
|
|
|
|
m_imageModelIndex = index;
|
|
m_imageIndex = index.row();
|
|
|
|
m_clippedImageModelIndex = m_preclippedImageModelIndex = QModelIndex();
|
|
|
|
loadImage();
|
|
enableDrawerButtons(true);
|
|
setModifyClipButton(false);
|
|
|
|
m_runningMode = NORMAL_MODE;
|
|
|
|
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
|
|
|
|
}
|
|
}
|
|
|
|
void ClippingStation::articleTreeViewClicked(QModelIndex index)
|
|
{
|
|
qDebug("articleTreeViewClicked()");
|
|
static int clipid, preclipid;
|
|
|
|
if( !index.isValid() )
|
|
return;
|
|
|
|
QAbstractItemModel *model = ui->clipsTreeView->model();
|
|
|
|
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
|
|
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
|
|
//if the user clicked on top level entries, just return
|
|
if ( index == preclipRootIndex ||
|
|
index == clipRootIndex )
|
|
{
|
|
ui->clipsTreeView->expand(index);
|
|
return;
|
|
}
|
|
|
|
int id;
|
|
if ( index.parent() == preclipRootIndex ||
|
|
index.parent().parent() == preclipRootIndex )
|
|
{
|
|
QModelIndex currentIndex;
|
|
|
|
m_clippedImageModelIndex = QModelIndex();
|
|
|
|
|
|
//if the selection is the Preclip(), then it will contain the id
|
|
if(index.parent() == preclipRootIndex)
|
|
{
|
|
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
|
|
currentIndex = model->index(0, 0, index);
|
|
}
|
|
else
|
|
{
|
|
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
|
|
currentIndex = index;
|
|
}
|
|
|
|
|
|
if (currentIndex == m_preclippedImageModelIndex )
|
|
return; //if its the same selection, do nothing
|
|
|
|
|
|
if ( preclipid != id || m_currentPreclipId == 0 )
|
|
{
|
|
if(m_runningMode == CLIPPING_MODE)
|
|
drawerResetPages();
|
|
|
|
clipid = 0;
|
|
m_currentClipId = 0;
|
|
preclipid = id;
|
|
m_currentPreclipId = id;
|
|
m_firstPageInClip = "";
|
|
}
|
|
|
|
if (ui->preclipButton->text() != tr("Preclip"))
|
|
{
|
|
QList<Tag> tags = m_tagsWrapper.ocrTags();
|
|
m_tagsWrapper.setOcrTags( tags );
|
|
|
|
QList<ImageCutout*> cutoutsList = ui->fullpageView->imageCutoutsList();
|
|
m_publication.currentIssue()->preclip(id).setImageCutouts(cutoutsList);
|
|
}
|
|
else
|
|
m_tagsWrapper.setOcrTags( m_publication.currentIssue()->preclip(id).tags() );
|
|
|
|
|
|
ui->fullpageView->hideImageCutouts();
|
|
ui->fullpageView->removePreselectedImageCutouts();
|
|
ui->fullpageView->setImageCutouts(m_publication.currentIssue()->preclip(id).imageCutoutsList());
|
|
|
|
|
|
m_tagsWrapper.showModel();
|
|
|
|
|
|
//m_cachedImages.clear();
|
|
m_publication.currentIssue()->preclip(id).getImagesLocalAndRemoateFiles(m_preclippedLocalImagesList, m_preclippedRemoteImagesList);
|
|
|
|
|
|
m_preclippedImageIndex = currentIndex.row();
|
|
m_preclippedImageModelIndex = currentIndex;
|
|
|
|
QString section = model->data(currentIndex, Qt::DisplayRole).toString();
|
|
section = section.left(section.indexOf("/"));
|
|
m_currentSectionName = section;
|
|
|
|
QString fname = m_preclippedRemoteImagesList[0]; //its int the format of /ClippingStation/cach/2009/10/17/162/16/0001.jpg
|
|
QStringList list = fname.split("/");
|
|
m_currentIssueDate = list[list.count()-6] + "-" + list[list.count()-5]+ "-" + list[list.count()-4];
|
|
m_publication.setCurrentIssue(m_currentIssueDate);
|
|
m_publication.currentIssue()->section(m_currentSectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
|
|
|
|
|
|
ui->clipsTreeView->selectionModel()->clearSelection();
|
|
ui->clipsTreeView->selectionModel()->setCurrentIndex(m_preclippedImageModelIndex, QItemSelectionModel::Select);
|
|
|
|
//ui->clipsTreeView->expand(m_preclippedImageModelIndex.parent().parent() );
|
|
//ui->clipsTreeView->expand(m_preclippedImageModelIndex.parent() );
|
|
ui->clipsTreeView->expand(m_preclippedImageModelIndex );
|
|
|
|
|
|
enableDrawerButtons(true);
|
|
setModifyClipButton(false);
|
|
|
|
m_runningMode = PRECLIPPING_MODE;
|
|
|
|
}
|
|
else if ( index.parent() == clipRootIndex ||
|
|
index.parent().parent() == clipRootIndex )
|
|
{
|
|
m_runningMode = CLIPPING_MODE;
|
|
QModelIndex currentIndex;
|
|
m_preclippedImageModelIndex = QModelIndex();
|
|
|
|
//qDebug("Columns count is %d", model->columnCount(index.parent()) );
|
|
|
|
if(index.parent() == clipRootIndex)
|
|
{
|
|
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
|
|
currentIndex = model->index(0, 0, index);
|
|
}
|
|
else
|
|
{
|
|
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
|
|
currentIndex = index;
|
|
}
|
|
|
|
if (currentIndex == m_clippedImageModelIndex )
|
|
return; //if its the same selection, do nothing
|
|
|
|
|
|
if(clipid != id || m_currentClipId == 0)
|
|
{
|
|
drawerResetPages();
|
|
clipid = id;
|
|
m_currentClipId = id;
|
|
preclipid = 0;
|
|
m_currentPreclipId = 0;
|
|
m_firstPageInClip = "";
|
|
}
|
|
ui->fullpageView->hideImageCutouts();
|
|
ui->fullpageView->removePreselectedImageCutouts();
|
|
ui->fullpageView->setImageCutouts(m_publication.currentIssue()->clip(id).imageCutoutsList());
|
|
|
|
|
|
//m_cachedImages.clear();
|
|
m_publication.currentIssue()->clip(id).getImagesLocalAndRemoateFiles(m_clippedLocalImagesList, m_clippedRemoteImagesList);
|
|
|
|
m_tagsWrapper.setOcrTags( m_publication.currentIssue()->clip(id).tags() );
|
|
m_tagsWrapper.showModel();
|
|
|
|
m_clippedImageIndex = currentIndex.row();
|
|
m_clippedImageModelIndex = currentIndex;
|
|
|
|
//ui->clipsTreeView->expand(m_clippedImageModelIndex.parent().parent() );
|
|
//ui->clipsTreeView->expand(m_clippedImageModelIndex.parent() );
|
|
ui->clipsTreeView->expand(m_clippedImageModelIndex );
|
|
|
|
ui->clipsTreeView->selectionModel()->clearSelection();
|
|
ui->clipsTreeView->selectionModel()->setCurrentIndex(m_clippedImageModelIndex, QItemSelectionModel::Select);
|
|
|
|
QString section = model->data(currentIndex, Qt::DisplayRole).toString();
|
|
section = section.left(section.indexOf("/"));
|
|
m_currentSectionName = section;
|
|
|
|
QString fname = m_clippedRemoteImagesList[0]; //its int the format of G:/socialhose/app/ClippingStation/debug/cach/2009/10/17/162/16/0001.jpg
|
|
QStringList list = fname.split("/");
|
|
m_currentIssueDate = list[list.count()-6] + "-" + list[list.count()-5]+ "-" + list[list.count()-4];
|
|
m_publication.setCurrentIssue(m_currentIssueDate);
|
|
m_publication.currentIssue()->section(m_currentSectionName).getLocalAndRemoteFiles(m_localImagesList, m_remoteImagesList);
|
|
|
|
loadClippingImages(id);
|
|
}
|
|
|
|
loadImage();
|
|
gotoClipPage();
|
|
}
|
|
|
|
void ClippingStation::clearStatusMessage()
|
|
{
|
|
ui->statusBar->clearMessage();
|
|
}
|
|
|
|
void ClippingStation::displayStatusMessage(const QString & status)
|
|
{
|
|
ui->statusBar->showMessage(status);
|
|
}
|
|
|
|
void ClippingStation::displayCoordinatesStatus(qreal x, qreal y, qreal width, qreal height)
|
|
{
|
|
ui->statusBar->displayCoordinates(x, y, width, height);
|
|
}
|
|
|
|
void ClippingStation::displayRotationAngleStatus(qreal angle)
|
|
{
|
|
ui->statusBar->displayRotationAngle(angle);
|
|
}
|
|
|
|
void ClippingStation::updateDrawerPageInformation()
|
|
{
|
|
ui->pageInformation->setText(QString("Page %1 of %2")
|
|
.arg(ui->stackedDrawerViewWidget->currentIndex() +1)
|
|
.arg(ui->stackedDrawerViewWidget->count()));
|
|
}
|
|
|
|
void ClippingStation::displayZoomStatus(qreal zoom)
|
|
{
|
|
ui->statusBar->displayZoom(zoom);
|
|
}
|
|
|
|
void ClippingStation::firstPage()
|
|
{
|
|
if ( m_imageModelIndex.isValid() )
|
|
{
|
|
int oldindex = m_imageIndex;
|
|
m_imageIndex = 0;
|
|
|
|
if (!loadImage())
|
|
{
|
|
m_imageIndex = oldindex;
|
|
return;
|
|
}
|
|
|
|
m_imageModelIndex = ui->issuesTreeView->model()->index(0, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
|
|
ui->issuesTreeView->selectionModel()->clearSelection();
|
|
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
|
|
|
|
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
|
|
|
|
}
|
|
}
|
|
|
|
void ClippingStation::previousPage()
|
|
{
|
|
if ( m_imageIndex > 0 && m_imageModelIndex.isValid() )
|
|
{
|
|
--m_imageIndex;
|
|
|
|
if (!loadImage())
|
|
{
|
|
++m_imageIndex;
|
|
return;
|
|
}
|
|
|
|
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageModelIndex.row()-1, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
|
|
ui->issuesTreeView->selectionModel()->clearSelection();
|
|
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
|
|
|
|
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
|
|
}
|
|
}
|
|
|
|
void ClippingStation::nextPage()
|
|
{
|
|
if( m_imageIndex < m_localImagesList.count()-1 )
|
|
{
|
|
m_imageIndex++;
|
|
|
|
if (!loadImage())
|
|
{
|
|
--m_imageIndex;
|
|
return;
|
|
}
|
|
|
|
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageModelIndex.row()+1, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
|
|
ui->issuesTreeView->selectionModel()->clearSelection();
|
|
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
|
|
|
|
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
|
|
}
|
|
}
|
|
|
|
void ClippingStation::lastPage()
|
|
{
|
|
if ( m_imageModelIndex.isValid() )
|
|
{
|
|
int oldindex = m_imageIndex;
|
|
m_imageIndex = m_localImagesList.count() -1;
|
|
if (!loadImage())
|
|
{
|
|
m_imageIndex = oldindex;
|
|
return;
|
|
}
|
|
|
|
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageIndex, 0,ui->issuesTreeView->model()->parent(m_imageModelIndex) );
|
|
ui->issuesTreeView->selectionModel()->clearSelection();
|
|
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
|
|
|
|
ui->gotoPageLineEdit->setText(QString("%1").arg(m_imageIndex+1) );
|
|
}
|
|
}
|
|
|
|
void ClippingStation::gotoPage()
|
|
{
|
|
bool ok;
|
|
int pagenum = ui->gotoPageLineEdit->text().toInt(&ok);
|
|
|
|
if(!ok)
|
|
return;
|
|
|
|
if( m_imageModelIndex.isValid() )
|
|
{
|
|
if ( pagenum < 1 || pagenum > m_localImagesList.count() )
|
|
return;
|
|
|
|
int oldindex = m_imageIndex;
|
|
m_imageIndex = pagenum -1 ;
|
|
|
|
if(!loadImage())
|
|
{
|
|
m_imageIndex = oldindex;
|
|
return;
|
|
}
|
|
|
|
m_imageModelIndex = ui->issuesTreeView->model()->index(m_imageIndex, 0, ui->issuesTreeView->model()->parent(m_imageModelIndex) );
|
|
ui->issuesTreeView->selectionModel()->clearSelection();
|
|
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
|
|
}
|
|
}
|
|
|
|
void ClippingStation::gotoClipPage()
|
|
{
|
|
//qDebug("gotoClipPage()");
|
|
|
|
QAbstractItemModel* model = ui->issuesTreeView->model();
|
|
int issuesCount = model->rowCount( QModelIndex() );
|
|
|
|
QString article;
|
|
if(m_runningMode == PRECLIPPING_MODE)
|
|
article = ui->clipsTreeView->model()->data(m_preclippedImageModelIndex, Qt::DisplayRole).toString();
|
|
else if(m_runningMode == CLIPPING_MODE)
|
|
article = ui->clipsTreeView->model()->data(m_clippedImageModelIndex , Qt::DisplayRole).toString();
|
|
|
|
for(int i=0; i< issuesCount; i++)
|
|
{
|
|
QString issue = model->index(i, 0, QModelIndex() ).data(Qt::DisplayRole).toString();
|
|
if(issue != m_currentIssueDate)
|
|
continue;
|
|
|
|
QModelIndex issueIndex = model->index(i, 0, QModelIndex() );
|
|
|
|
int sectionsCount = model->rowCount(issueIndex);
|
|
for(int j=0; j < sectionsCount; j++)
|
|
{
|
|
QString section = model->index(j, 0, issueIndex).data(Qt::DisplayRole).toString();
|
|
if( article.split("/").at(0) != section )// != m_currentSectionName)
|
|
continue;
|
|
|
|
QModelIndex sectionIndex = model->index(j, 0, issueIndex);
|
|
int pagesCount = model->rowCount(sectionIndex);
|
|
|
|
for(int k=0; k< pagesCount; k++)
|
|
{
|
|
QString page = model->index(k, 0, sectionIndex).data(Qt::DisplayRole).toString();
|
|
if( !article.endsWith(page) )
|
|
continue;
|
|
|
|
m_imageModelIndex = model->index(k, 0, sectionIndex);
|
|
ui->issuesTreeView->selectionModel()->clearSelection();
|
|
ui->issuesTreeView->selectionModel()->setCurrentIndex(m_imageModelIndex, QItemSelectionModel::Select);
|
|
|
|
ui->issuesTreeView->expand(m_imageModelIndex.parent().parent());
|
|
ui->issuesTreeView->expand(m_imageModelIndex.parent());
|
|
//ui->issuesTreeView->expand(m_imageModelIndex);
|
|
}
|
|
return;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
void ClippingStation::rotate(double i)
|
|
{
|
|
ui->fullpageView->rotate(i);
|
|
if(i == 0)
|
|
ui->saveRotateButton->setEnabled(false);
|
|
else
|
|
ui->saveRotateButton->setEnabled(true);
|
|
}
|
|
|
|
void ClippingStation::saveImageRotation()
|
|
{
|
|
//we first get the ORIGINAL image from the file server
|
|
//we get its name/path
|
|
QString localeImage, remoteImage;
|
|
if(m_runningMode == NORMAL_MODE)
|
|
{
|
|
localeImage = m_localImagesList[m_imageIndex];
|
|
remoteImage = m_remoteImagesList[m_imageIndex];
|
|
}
|
|
else if (m_runningMode == PRECLIPPING_MODE)
|
|
{
|
|
localeImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
|
|
remoteImage = m_preclippedRemoteImagesList[m_preclippedImageIndex];
|
|
}
|
|
else if (m_runningMode == CLIPPING_MODE )
|
|
{
|
|
localeImage = m_clippedLocalImagesList[m_clippedImageIndex];
|
|
remoteImage = m_clippedRemoteImagesList[m_clippedImageIndex];
|
|
}
|
|
|
|
QImage image(remoteImage);
|
|
|
|
//do the roation
|
|
double rotate = ui->rotateSpinBox->value();
|
|
|
|
QTransform mx;
|
|
mx = mx.rotate(rotate);
|
|
image = image.transformed(mx, Qt::SmoothTransformation);
|
|
|
|
//now we delete the original image, and save this back to that location
|
|
if (QFile::remove(remoteImage) )
|
|
{
|
|
image.save(remoteImage, "jpg", JPG_SAVE_QUALITY);
|
|
//also remove the file from the local cache
|
|
QFile::remove(localeImage);
|
|
//reset the rotate spin box
|
|
ui->rotateSpinBox->setValue(0);
|
|
//and re open the new image after it has been saved
|
|
m_cachedImages[ localeImage ] = false; //to force to reload the new image from server
|
|
loadImage();
|
|
}
|
|
|
|
//also, load the 300dpi image, and rotate it as well
|
|
QFileInfo inf(remoteImage);
|
|
QString img300dpi= inf.absolutePath() + "/" + HIGH_RES_IMAGE_DIR + inf.fileName();
|
|
|
|
if(!QFile::exists(img300dpi))
|
|
return;
|
|
|
|
QImage image300(img300dpi);
|
|
image300 = image300.transformed(mx, Qt::SmoothTransformation);
|
|
//now we delete the original image, and save this back to that location
|
|
if (QFile::remove(img300dpi) )
|
|
image300.save(img300dpi, "jpg", JPG_SAVE_QUALITY);
|
|
}
|
|
|
|
|
|
qreal ClippingStation::zoomOut()
|
|
{
|
|
ui->bestFitButton->setChecked(false);
|
|
ui->widthFitButton->setChecked(false);
|
|
ui->fullpageView->setPageLayout(ACTUAL_SIZE);
|
|
|
|
return ui->fullpageView->zoom(false);
|
|
}
|
|
|
|
qreal ClippingStation::zoomIn()
|
|
{
|
|
ui->bestFitButton->setChecked(false);
|
|
ui->widthFitButton->setChecked(false);
|
|
ui->fullpageView->setPageLayout(ACTUAL_SIZE);
|
|
|
|
return ui->fullpageView->zoom(true);
|
|
}
|
|
|
|
qreal ClippingStation::actualSize()
|
|
{
|
|
ui->bestFitButton->setChecked(false);
|
|
ui->widthFitButton->setChecked(false);
|
|
ui->fullpageView->setPageLayout(ACTUAL_SIZE);
|
|
|
|
return ui->fullpageView->actualSize();
|
|
}
|
|
|
|
void ClippingStation::bestFit()
|
|
{
|
|
ui->bestFitButton->setChecked(true);
|
|
ui->widthFitButton->setChecked(false);
|
|
ui->fullpageView->setPageLayout(BEST_FIT);
|
|
}
|
|
|
|
void ClippingStation::widthFit()
|
|
{
|
|
ui->bestFitButton->setChecked(false);
|
|
ui->widthFitButton->setChecked(true);
|
|
ui->fullpageView->setPageLayout(WIDTH_FIT);
|
|
}
|
|
|
|
qreal ClippingStation::drawerZoomOut()
|
|
{
|
|
ui->drawerBestFitButton->setChecked(false);
|
|
ui->drawerWidthFitButton->setChecked(false);
|
|
|
|
|
|
int index = ui->stackedDrawerViewWidget->currentIndex();
|
|
|
|
//ui->stackedDrawerViewWidget->setCurrentIndex(0);
|
|
qreal scale = 1.0;
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(i);
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
scale = view->zoom(false);
|
|
m_currentA4Scale = view->currentScale();
|
|
}
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(index);
|
|
|
|
|
|
|
|
return scale;
|
|
}
|
|
|
|
qreal ClippingStation::drawerZoomIn()
|
|
{
|
|
ui->drawerBestFitButton->setChecked(false);
|
|
ui->drawerWidthFitButton->setChecked(false);
|
|
|
|
|
|
int index = ui->stackedDrawerViewWidget->currentIndex();
|
|
|
|
//ui->stackedDrawerViewWidget->setCurrentIndex(0);
|
|
qreal scale = 1.0;
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(i);
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
scale = view->zoom(true);
|
|
m_currentA4Scale = view->currentScale();
|
|
}
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(index);
|
|
|
|
return scale;
|
|
}
|
|
|
|
qreal ClippingStation::drawerActualSize()
|
|
{
|
|
ui->drawerBestFitButton->setChecked(false);
|
|
ui->drawerWidthFitButton->setChecked(false);
|
|
|
|
int index = ui->stackedDrawerViewWidget->currentIndex();
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(0);
|
|
qreal scale = 1.0;
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
view->setPageLayout(ACTUAL_SIZE);
|
|
scale = view->actualSize();
|
|
m_currentA4Scale = view->currentScale();
|
|
}
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(index);
|
|
|
|
|
|
return scale;
|
|
}
|
|
|
|
void ClippingStation::drawerBestFit()
|
|
{
|
|
ui->drawerBestFitButton->setChecked(true);
|
|
ui->drawerWidthFitButton->setChecked(false);
|
|
|
|
int index = ui->stackedDrawerViewWidget->currentIndex();
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(0);
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
view->setPageLayout(BEST_FIT);
|
|
m_currentA4Scale = view->currentScale();
|
|
}
|
|
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(index);
|
|
}
|
|
|
|
void ClippingStation::drawerWidthFit()
|
|
{
|
|
ui->drawerBestFitButton ->setChecked(false);
|
|
ui->drawerWidthFitButton->setChecked(true);
|
|
|
|
int index = ui->stackedDrawerViewWidget->currentIndex();
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(0);
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
view->setPageLayout(WIDTH_FIT);
|
|
m_currentA4Scale = view->currentScale();
|
|
}
|
|
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(index);
|
|
}
|
|
|
|
bool ClippingStation::loadImage()
|
|
{
|
|
// qDebug("loadImage()");
|
|
// clock_t start = clock();
|
|
static bool firstPage = true;
|
|
|
|
m_trackingTimer.stop();
|
|
/*
|
|
------------------------
|
|
| id_user_page_track |
|
|
| id_users |
|
|
| id_section_pages |
|
|
| last_modified |
|
|
| first_access |
|
|
| last_access |
|
|
| issue_created |
|
|
| id_publication |
|
|
| id_publication_type |
|
|
| publication_language |
|
|
| publication_market |
|
|
| issue_date |
|
|
| seconds |
|
|
------------------------
|
|
*/
|
|
|
|
if(!firstPage && m_trackingSeconds > 0)
|
|
{
|
|
QString language = "en";
|
|
if(m_publication.language() == "Arabic")
|
|
language = "ar";
|
|
m_user.updateTrack(m_currentPageId, m_trackingSeconds);
|
|
}
|
|
|
|
bool ret = true;
|
|
QString localeImage, remoteImage;
|
|
|
|
if (m_runningMode == NORMAL_MODE)
|
|
{
|
|
qDebug() << "\tImage: "<< m_remoteImagesList[m_imageIndex];
|
|
localeImage = m_localImagesList[m_imageIndex];
|
|
remoteImage = m_remoteImagesList[m_imageIndex];
|
|
}
|
|
else if (m_runningMode == PRECLIPPING_MODE)
|
|
{
|
|
qDebug() << "\tPreclipping Image: "<< m_preclippedRemoteImagesList[m_preclippedImageIndex];
|
|
localeImage = m_preclippedLocalImagesList[m_preclippedImageIndex];
|
|
remoteImage = m_preclippedRemoteImagesList[m_preclippedImageIndex];
|
|
}
|
|
else if (m_runningMode == CLIPPING_MODE )
|
|
{
|
|
qDebug() << "\tClipping Image: "<< m_clippedRemoteImagesList[m_clippedImageIndex];
|
|
localeImage = m_clippedLocalImagesList[m_clippedImageIndex];
|
|
remoteImage = m_clippedRemoteImagesList[m_clippedImageIndex];
|
|
}
|
|
|
|
/*int lockedBy;
|
|
if( isImageLocked(localeImage, lockedBy) )
|
|
{
|
|
QString username = User::username(m_slaveDatabase, lockedBy);
|
|
QMessageBox::warning(this, tr("Page Locked"), tr("You cant load this page because its locked by user (%1)").arg(username) );
|
|
return false;
|
|
}
|
|
|
|
lockImage(localeImage);*/
|
|
|
|
if( !m_cachedImages[ localeImage ] )
|
|
{
|
|
if ( !m_imageCachingDialog.cachingThreadStarted() )
|
|
{
|
|
ret = cacheOnePage(remoteImage, localeImage);
|
|
}
|
|
else
|
|
{
|
|
m_imageCachingDialog.pause();
|
|
ret = cacheOnePage(remoteImage, localeImage);
|
|
}
|
|
}
|
|
|
|
if(ret)
|
|
ret = ui->fullpageView->load(localeImage);
|
|
|
|
if(ret)
|
|
{
|
|
QStringList parts = localeImage.split("/");
|
|
QString image = parts[parts.count()-1];
|
|
m_currentPageId = getImageId(image);
|
|
loadImageHighlights(m_currentPageId);//load the highlights
|
|
}
|
|
|
|
// double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
// qDebug("loadImage() Time: %f", diff);
|
|
|
|
cache();
|
|
|
|
if(m_isPaused) //if in pause state, change it to resume.
|
|
pauseTracking();
|
|
|
|
m_trackingSeconds = 0;
|
|
m_trackingTimer.start(1000);
|
|
|
|
int pubIssueId = publicationIssueId(m_publication.id(), m_publication.currentIssue()->date());
|
|
int issueSecId = issueSectionsId(pubIssueId, m_publication.currentIssue()->section(m_currentSectionName).id());
|
|
|
|
m_user.track(m_currentPageId, m_publication.id(), pubIssueId, issueSecId,
|
|
m_publication.type(), m_publication.country().toInt(),
|
|
m_publication.language(), m_publication.currentIssue()->date(), m_publication.currentIssue()->created());
|
|
|
|
firstPage = false;
|
|
|
|
return ret;
|
|
}
|
|
|
|
void ClippingStation::cache()
|
|
{
|
|
//qDebug("cache()");
|
|
clock_t start = clock();
|
|
|
|
if(m_runningMode == NORMAL_MODE)
|
|
m_imageCachingDialog.setValues(m_remoteImagesList, m_localImagesList);
|
|
else if(m_runningMode == CLIPPING_MODE )
|
|
m_imageCachingDialog.setValues(m_clippedRemoteImagesList, m_clippedLocalImagesList);
|
|
else if(m_runningMode == PRECLIPPING_MODE )
|
|
m_imageCachingDialog.setValues(m_preclippedRemoteImagesList, m_preclippedLocalImagesList);
|
|
|
|
m_imageCachingDialog.startCaching();
|
|
m_imageCachingDialog.show(); //m_imageCachingDialog.exec();
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
qDebug("cache() Time: %f", diff);
|
|
|
|
}
|
|
|
|
bool ClippingStation::cacheOnePage(QString srcPage, QString dstPage)
|
|
{
|
|
clock_t start = clock();
|
|
|
|
m_imageCachingDialog.pause();
|
|
return m_imageCachingDialog.cacheOnePage(srcPage, dstPage);
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
qDebug("cacheOnePage() Time: %f", diff);
|
|
}
|
|
|
|
bool ClippingStation::recursiveDelete(const QDir &dir)
|
|
{
|
|
QList<QFileInfo> infLst = dir.entryInfoList();
|
|
|
|
foreach(QFileInfo finfo, infLst )
|
|
{
|
|
if(finfo.fileName() == "." || finfo.fileName() == ".." )
|
|
continue;
|
|
|
|
if(finfo.isDir() )
|
|
{
|
|
QDir subDir(finfo.absoluteFilePath());
|
|
qDebug() << "SubDir: " << subDir.absolutePath().toLocal8Bit();
|
|
QDir dir1 = dir;
|
|
|
|
if ( recursiveDelete(subDir) )
|
|
{
|
|
dir1.cdUp();
|
|
if ( !dir1.rmdir(finfo.absoluteFilePath() ) )
|
|
{
|
|
qDebug() << "Error deleting directory: " << finfo.absoluteFilePath().toLocal8Bit();
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ //file
|
|
QDir dir1;
|
|
if( !dir1.remove(finfo.absoluteFilePath()) )
|
|
qDebug() << "Error deleting file: " << finfo.absoluteFilePath();
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ClippingStation::searchKeyword()
|
|
{
|
|
QString search = ui->keywordLineEdit->text();
|
|
if( search.isEmpty() || search.isNull() )
|
|
return;
|
|
|
|
m_tagsWrapper.searchKeyword(m_masterDatabase, search);
|
|
}
|
|
|
|
void ClippingStation::checkAllKeywords()
|
|
{
|
|
m_tagsWrapper.checkAllKeywords();
|
|
}
|
|
|
|
void ClippingStation::uncheckAllKeywords()
|
|
{
|
|
m_tagsWrapper.uncheckAllKeywords();
|
|
}
|
|
|
|
void ClippingStation::selectKeyword()
|
|
{
|
|
m_tagsWrapper.selectKeyword();
|
|
}
|
|
|
|
void ClippingStation::clipsTreeContextMenu(QPoint point)
|
|
{
|
|
QModelIndex index = ui->clipsTreeView->indexAt(point);
|
|
if( index.isValid() )
|
|
{
|
|
point.setY(point.y() + 25);
|
|
QAbstractItemModel *model = ui->clipsTreeView->model();
|
|
|
|
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
|
|
QModelIndex clipRootIndex = model->index(1, 0, QModelIndex() );
|
|
//if the user clicked on top level entries, just return
|
|
if ( index == preclipRootIndex ||
|
|
index == clipRootIndex )
|
|
return;
|
|
|
|
int id;
|
|
if ( index.parent() == preclipRootIndex ||
|
|
index.parent().parent() == preclipRootIndex )
|
|
{
|
|
m_runningMode = PRECLIPPING_MODE;
|
|
QModelIndex currentIndex;
|
|
|
|
m_clippedImageModelIndex = QModelIndex();
|
|
|
|
|
|
//if the selection is the Preclip(), then it will contain the id
|
|
if(index.parent() == preclipRootIndex)
|
|
{
|
|
id = model->index(index.row(), 1, index.parent() ).data(Qt::DisplayRole).toInt();
|
|
//currentIndex = index.child(0, 0);
|
|
}
|
|
else
|
|
{
|
|
id = model->index(index.parent().row(), 1, index.parent().parent() ).data(Qt::DisplayRole).toInt();
|
|
//currentIndex = index;
|
|
}
|
|
|
|
m_preclipContextMenu->exec( ui->clipsTreeView->mapToGlobal(point));
|
|
}
|
|
else
|
|
{
|
|
m_clipContextMenu->exec( ui->clipsTreeView->mapToGlobal(point));
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClippingStation::issueTreeContextMenu(QPoint point)
|
|
{
|
|
QModelIndex index = ui->issuesTreeView->indexAt(point);
|
|
if( index.isValid() )
|
|
{
|
|
point.setY(point.y() + 25);
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
if(index == QModelIndex() )
|
|
return;
|
|
|
|
if(model->parent(index) == QModelIndex() )
|
|
{
|
|
m_issueContextMenu->exec(ui->issuesTreeView->mapToGlobal(point));
|
|
return;
|
|
}
|
|
|
|
if(model->parent(index).parent() == QModelIndex() )
|
|
return;
|
|
|
|
if(model->parent(index).parent().parent() == QModelIndex() ) //its the image
|
|
m_issuePageContextMenu->exec( ui->issuesTreeView->mapToGlobal(point));
|
|
else
|
|
qDebug() << "not an image selection";
|
|
}
|
|
}
|
|
|
|
void ClippingStation::keywordsTreeContextMenu(QPoint point)
|
|
{
|
|
QModelIndex index = ui->treeView->indexAt(point);
|
|
if(!index.isValid())
|
|
return;
|
|
|
|
point.setY(point.y()+25);
|
|
// QAbstractItemModel *model = ui->treeView->model();
|
|
|
|
m_keywordsContextMenu->exec( ui->treeView->mapToGlobal(point));
|
|
}
|
|
|
|
void ClippingStation::preclip()
|
|
{
|
|
qDebug("preclip()");
|
|
|
|
QList<ImageCutout *> cutoutsList = ui->fullpageView->imageCutoutsList();
|
|
if(cutoutsList.count() == 0)
|
|
{
|
|
QMessageBox::information(this, "No selections", "Please select at least one cutout to be able to clip");
|
|
return;
|
|
}
|
|
|
|
QList<Tag> tags = m_tagsWrapper.ocrTags();
|
|
if( tags.count() == 0 )
|
|
{
|
|
QMessageBox::information(this, "No Tags", "Please add the associated tags to be able to clip");
|
|
return;
|
|
}
|
|
|
|
|
|
qreal image_size = ui->fullpageView->pageSize();
|
|
|
|
if(ui->preclipButton->text() == tr("Modify"))
|
|
{
|
|
m_publication.currentIssue()->preclip(m_currentPreclipId).updateArticle(m_masterDatabase, m_publication, tags, cutoutsList, image_size);
|
|
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, m_currentPreclipId, false, true);
|
|
}
|
|
else
|
|
{
|
|
int articleId = Article::clip(m_masterDatabase, m_publication, m_user.id(), tags, cutoutsList, m_currentSectionName, image_size, 0, 1, "");
|
|
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, articleId, false, false);
|
|
}
|
|
|
|
drawerResetPages();
|
|
m_firstPageInClip = ""; //reset pages for clipping
|
|
m_currentPreclipId = 0; //reset the preclip id;
|
|
m_currentClipId = 0;
|
|
|
|
|
|
//loadIssuesWithPreclipsOnly();
|
|
|
|
m_tagsWrapper.clearTags();
|
|
ui->fullpageView->removeImageCutouts();
|
|
|
|
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
|
|
|
|
setModifyPreclipButton(false);
|
|
|
|
m_runningMode = NORMAL_MODE;
|
|
|
|
ui->statusBar->showMessage("Preclipping successfull");
|
|
|
|
qDebug("end of preclip()");
|
|
}
|
|
|
|
void ClippingStation::clip()
|
|
{
|
|
qDebug("clip()");
|
|
|
|
qDebug("before cutoutList()");
|
|
QList<ImageCutout *> cutoutsList = ui->fullpageView->imageCutoutsList();
|
|
|
|
if(cutoutsList.count() == 0)
|
|
{
|
|
QMessageBox::information(this, "No selections", "Please select at least one area to be able to clip");
|
|
return;
|
|
}
|
|
|
|
qDebug("before ocrTags()");
|
|
QList<Tag> tags = m_tagsWrapper.ocrTags();
|
|
if( tags.count() == 0 )
|
|
{
|
|
QMessageBox::information(this, "No Tags", "Please add the associated tags to be able to clip");
|
|
return;
|
|
}
|
|
|
|
static QSqlDatabase db = m_masterDatabase.cloneDatabase(m_masterDatabase, "master2222");
|
|
db.open();
|
|
|
|
if (m_runningMode != CLIPPING_MODE)
|
|
{
|
|
int cutoutsCount = totalNumberOfCutoutsInDrawer();
|
|
if( cutoutsCount <= 0 )
|
|
{
|
|
QMessageBox::information(this, "Blank clipping", "Please add the cut outs be able to clip");
|
|
return;
|
|
}
|
|
|
|
QStringList pages = emptyDrawerPages();
|
|
if(pages.count() > 0)
|
|
{
|
|
QString page;
|
|
if(pages.count() == 1)
|
|
page = QString("Page (%1) in drawer is empty, please remove it before clipping").arg(pages[0]);
|
|
else
|
|
page = QString("Pages (%1) in drawer are empty, please remove them before clipping").arg(pages.join(","));
|
|
|
|
QMessageBox::information(this, "Empty pages", page);
|
|
return;
|
|
}
|
|
|
|
if( cutoutsList.count() > cutoutsCount )
|
|
{
|
|
switch( QMessageBox::question(
|
|
this,
|
|
tr("Warning"),
|
|
tr("You only copied %1/%2 cutouts from left pane, Do you want to CONTINUE the clipping process?").arg( cutoutsCount ).arg( cutoutsList.count() ),
|
|
QMessageBox::Yes |
|
|
QMessageBox::No,
|
|
QMessageBox::No) )
|
|
{
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_runningMode == PRECLIPPING_MODE)
|
|
{
|
|
int images_number = ui->stackedDrawerViewWidget->count(); //the count of image
|
|
QString text = ui->fullpageView->text();
|
|
|
|
bool isArabic = (m_publication.language() == "Arabic");
|
|
m_publication.currentIssue()->preclip(m_currentPreclipId).updateTags(m_masterDatabase, tags, isArabic);
|
|
m_publication.currentIssue()->preclip(m_currentPreclipId).updateImagesNumber(m_masterDatabase, images_number);
|
|
m_publication.currentIssue()->preclip(m_currentPreclipId).updateProminence(m_masterDatabase, m_publication, tags, m_user.id());
|
|
|
|
QList<QImage> list = createClipImages();
|
|
bool ret = true;
|
|
|
|
if(m_useFtp)
|
|
{
|
|
QFuture<bool> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFtpServer(m_currentIssueDate, m_currentPreclipId, list, true, m_masterDatabase); });
|
|
m_saveClipImagesToFtpServerWatcher.setFuture(future);
|
|
}
|
|
else
|
|
{
|
|
QFuture<int> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFileServer(m_currentIssueDate, m_currentPreclipId, list); });
|
|
m_saveClipImagesToFileServerWatcher.setFuture(future); //ret = saveClipImagesToFileServer(m_currentPreclipId, list); //save the clip images in the clip directories
|
|
//ret = saveClipImagesToFileServer(m_currentIssueDate, m_currentPreclipId, list, true, m_masterDatabase);
|
|
}
|
|
|
|
if(!m_publication.skipOcr())
|
|
{
|
|
qDebug() << m_publication.name() << " not skip OCR, Insert to db";
|
|
bool isArabic = (m_publication.language() == "Arabic");
|
|
QFuture<bool> future2 = QtConcurrent::run([=]() mutable { return addTextToClip(m_currentPreclipId, cutoutsList, db, isArabic); });
|
|
m_addTextToClipWatcher.setFuture(future2);
|
|
}
|
|
else
|
|
qDebug() << m_publication.name() << " has skip OCR set, wont insert text to db";
|
|
|
|
|
|
if(!ret)
|
|
{
|
|
m_publication.currentIssue()->preclip(m_currentPreclipId).updateStatus(m_masterDatabase, 1);
|
|
ui->statusBar->showMessage("Clipping Error");
|
|
}
|
|
else
|
|
{
|
|
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, m_currentPreclipId, true, true);
|
|
ui->statusBar->showMessage("Clipping successfull");
|
|
}
|
|
}
|
|
else if (m_runningMode == CLIPPING_MODE)
|
|
{
|
|
bool isArabic = (m_publication.language() == "Arabic");
|
|
m_publication.currentIssue()->clip(m_currentClipId).updateTags(m_masterDatabase, tags, isArabic);
|
|
m_publication.currentIssue()->clip(m_currentClipId).updateProminence(m_masterDatabase, m_publication, tags, m_user.id());
|
|
|
|
ui->statusBar->showMessage("Clip modified successfully");
|
|
}
|
|
else //fresh clip
|
|
{
|
|
|
|
qreal image_size = ui->fullpageView->pageSize();
|
|
int images_number = ui->stackedDrawerViewWidget->count(); //the cound of image
|
|
QString text = ui->fullpageView->text();
|
|
|
|
int id_article = Article::clip(m_masterDatabase, m_publication, m_user.id(), tags, cutoutsList, m_currentSectionName, image_size, images_number, 1);
|
|
|
|
//create the images
|
|
QList<QImage> list = createClipImages();
|
|
bool ret = true;
|
|
if(m_useFtp)
|
|
{
|
|
QFuture<bool> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFtpServer(m_currentIssueDate, id_article, list, false, m_masterDatabase); });
|
|
m_saveClipImagesToFtpServerWatcher.setFuture(future);
|
|
}
|
|
else
|
|
{
|
|
QFuture<int> future = QtConcurrent::run([=]() mutable { return saveClipImagesToFileServer(m_currentIssueDate, id_article, list); });
|
|
m_saveClipImagesToFileServerWatcher.setFuture(future); //ret = saveClipImagesToFileServer(m_currentPreclipId, list); //save the clip images in the clip directories
|
|
//ret = saveClipImagesToFileServer(m_currentIssueDate, id_article, list, true, m_masterDatabase);
|
|
}
|
|
|
|
if(!m_publication.skipOcr())
|
|
{
|
|
qDebug() << m_publication.name() << " No skip OCR set, insert text to db";
|
|
//QSqlDatabase db = m_masterDatabase.cloneDatabase(m_masterDatabase, "master2222");
|
|
//db.open();
|
|
bool isArabic = (m_publication.language() == "Arabic");
|
|
QFuture<bool> future2 = QtConcurrent::run([=]() mutable { return addTextToClip(id_article, cutoutsList, db, isArabic); });
|
|
m_addTextToClipWatcher.setFuture(future2);
|
|
}
|
|
else
|
|
qDebug() << m_publication.name() << " has skip OCR set, wont insert text to db";
|
|
|
|
if(!ret)
|
|
{
|
|
Article::deleteArticle(m_masterDatabase, id_article);
|
|
ui->statusBar->showMessage("Clipping Error");
|
|
}
|
|
else
|
|
{
|
|
m_publication.currentIssue()->addArticleToView(m_masterDatabase, ui->clipsTreeView, id_article, true, false);
|
|
ui->statusBar->showMessage("Clipping successfull");
|
|
}
|
|
}
|
|
|
|
|
|
drawerResetPages();
|
|
m_firstPageInClip = ""; //reset pages for clipping
|
|
m_currentPreclipId = 0; //reset the preclip id;
|
|
m_currentClipId = 0;
|
|
|
|
|
|
//if (m_filterMode == PRECLIPSONLY_FILTER)
|
|
//loadIssuesWithPreclipsOnly();
|
|
ui->fullpageView->removeImageCutouts();
|
|
|
|
m_publication.addImageCutoutsToIssues(ui->issuesTreeView, false);
|
|
m_tagsWrapper.clearTags();
|
|
//m_tagsWrapper.showModel();
|
|
|
|
m_runningMode = NORMAL_MODE;
|
|
|
|
if (m_filterMode == PRECLIPSONLY_FILTER)
|
|
{
|
|
//go to the next preclip
|
|
QAbstractItemModel *model = ui->clipsTreeView->model();
|
|
|
|
QModelIndex preclipRootIndex = model->index(0, 0, QModelIndex() );
|
|
//if(preclipRootIndex.model()->children().count() > 0)
|
|
{
|
|
QModelIndex pindex = model->index(0, 0, preclipRootIndex);
|
|
if(pindex.isValid())
|
|
articleTreeViewClicked(pindex);
|
|
else
|
|
{
|
|
//we have reached the end of this issues preclip, so, remove the issue from list.
|
|
m_publication.removeIssueFromIssues(ui->issuesTreeView, m_currentIssueDate);
|
|
m_currentIssueDate = "";
|
|
//now go to the next issue
|
|
QAbstractItemModel *model = ui->issuesTreeView->model();
|
|
|
|
QModelIndex issuesIndex = model->index(0, 0, QModelIndex() );
|
|
if( issuesIndex.isValid() )
|
|
issueTreeViewItemClicked(issuesIndex);
|
|
else
|
|
{
|
|
//remove the publication from the drop-down list
|
|
ui->preclippedPublicationComboBox->removeItem(ui->preclippedPublicationComboBox->currentIndex());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
qDebug("end of clip()");
|
|
}
|
|
|
|
void ClippingStation::drawerResetPages()
|
|
{
|
|
qDebug("drawerResetPages()");
|
|
|
|
int count = ui->stackedDrawerViewWidget->count();
|
|
for(int i=count -1 ; i >= 0; i--)
|
|
{
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(i);
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
ui->stackedDrawerViewWidget->removeWidget( ui->stackedDrawerViewWidget->widget(i) );
|
|
delete view;
|
|
}
|
|
drawerAddPage(true);
|
|
|
|
}
|
|
|
|
void ClippingStation::drawerAddPage(bool isfirst)
|
|
{
|
|
|
|
DrawerView * newview = new DrawerView(isfirst, ui->page);
|
|
|
|
qreal oldscale = 1.0; //for the first page insertion
|
|
//first we restore all the current pages to actual size, add the new page, and then restore them back to current size;
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
oldscale = view->actualSize();
|
|
}
|
|
|
|
ui->stackedDrawerViewWidget->addWidget(newview);
|
|
|
|
//restore to old scale value
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
view->setScale(oldscale);
|
|
}
|
|
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(ui->stackedDrawerViewWidget->count() - 1);
|
|
|
|
if(isfirst)
|
|
drawerBestFit(); //best fit mod
|
|
// else
|
|
// newview->setPageLayout(ACTUAL_SIZE);
|
|
m_currentA4Scale = newview->currentScale();
|
|
//qDebug("Add Page scale %.2f", m_currentA4Scale);
|
|
|
|
updateDrawerPageInformation();
|
|
connect(newview, SIGNAL(createThumbnail()), this, SLOT(createThumbnail()));
|
|
|
|
}
|
|
|
|
void ClippingStation::drawerRemovePage()
|
|
{
|
|
int i = ui->stackedDrawerViewWidget->currentIndex();
|
|
if (i == 0) //first page
|
|
{
|
|
QMessageBox::critical(this, "Error", "You cant remove the first page in drawer");
|
|
return;
|
|
}
|
|
|
|
switch( QMessageBox::question(
|
|
this,
|
|
tr("Delete Page"),
|
|
tr("Delete page from the Drawer, are you sure?"),
|
|
QMessageBox::Yes |
|
|
QMessageBox::No,
|
|
QMessageBox::No) )
|
|
{
|
|
case QMessageBox::Yes:
|
|
break;
|
|
case QMessageBox::No:
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
//DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
//view->removeEventFilter(this);
|
|
ui->stackedDrawerViewWidget->removeWidget( ui->stackedDrawerViewWidget->widget(i) );
|
|
updateDrawerPageInformation();
|
|
}
|
|
|
|
void ClippingStation::drawerPreviousPage()
|
|
{
|
|
int currentIndex = ui->stackedDrawerViewWidget->currentIndex();
|
|
if (currentIndex != 0)
|
|
{
|
|
A4Scale();
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(currentIndex-1);
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget());
|
|
view->setScale(m_currentA4Scale);
|
|
updateDrawerPageInformation();
|
|
}
|
|
}
|
|
|
|
void ClippingStation::drawerNextPage()
|
|
{
|
|
int currentIndex = ui->stackedDrawerViewWidget->currentIndex();
|
|
if (currentIndex != ui->stackedDrawerViewWidget->count() - 1)
|
|
{
|
|
A4Scale();
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(currentIndex+1);
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->currentWidget());
|
|
view->setScale(m_currentA4Scale);
|
|
updateDrawerPageInformation();
|
|
}
|
|
}
|
|
|
|
QList<QImage> ClippingStation::createClipImages()
|
|
{
|
|
QList<QImage> list;
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(i);
|
|
if(view->cutoutsCount() > 0)
|
|
{
|
|
QImage img = view->screenShot();
|
|
list.append(img);
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
int ClippingStation::saveClipImagesToFileServer(QString currentIssue, int id_article, QList<QImage> &list)
|
|
{
|
|
g_clipMutex.lock();
|
|
qDebug("saveClipImages() for article %d", id_article);
|
|
//we save the images on this format ClippingsPath/YYYY/MM/DD/ID_ARTICLE-X
|
|
|
|
QString path = SystemConfiguration::clippingsPath();
|
|
|
|
QStringList dateSplit = currentIssue.split("-");
|
|
path = path + QString("%1/%2/%3/").arg(dateSplit[0], 4, QChar('0')).arg(dateSplit[1], 2, QChar('0')).arg(dateSplit[2], 2, QChar('0'));
|
|
|
|
|
|
#ifdef Q_WS_WIN
|
|
path = SystemConfiguration::clippingsWindowsDriveLetter() + path; //if we are under Windows, add Windows drive letter
|
|
#endif
|
|
QDir dir;
|
|
|
|
qDebug("saveClipImages() for article %d: create the directory structure", id_article);
|
|
if( !dir.exists(path) )
|
|
{
|
|
if( !dir.mkpath(path) )
|
|
{
|
|
QMessageBox::critical(0, tr("saveClipImagesToFileServer() Error"), tr("Error creating directory structure for clippings!"));
|
|
qDebug("saveClipImagesToFileServer(): Error creating directory ");
|
|
g_clipMutex.unlock();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
bool ret = true;
|
|
int i = 0;
|
|
|
|
//first save the file locally, and then move it the file server
|
|
qDebug("saveClipImages(): create clippings directory in cache");
|
|
|
|
QString localpath = m_cacheDir + "clippings/";
|
|
QDir dir2;
|
|
if( !dir2.exists(localpath) )
|
|
{
|
|
if( !dir2.mkpath(localpath) )
|
|
{
|
|
QMessageBox::critical(0, tr("saveClipImagesToFileServer() Error"), tr("Error creating directory structure for local clippings!"));
|
|
qDebug("saveClipImagesToFileServer(): Error creating directory ");
|
|
g_clipMutex.unlock();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
qDebug("saveClipImages(): trying to save %d images", list.count() );
|
|
QFile file;
|
|
for(i=0; i< list.count(); i++)
|
|
{
|
|
QString fname = QString("%1-%2.jpg").arg(id_article).arg(i+1);
|
|
//if( file.exists(localpath + fname) || file.exists(path + fname) ) //try to remove the files if they exist
|
|
{
|
|
file.remove(localpath+ fname); //remove the file from cache if it already exist (from previous un-successful clip)
|
|
file.remove(path + fname); //and from the file server
|
|
}
|
|
|
|
ret = list[i].save(localpath + fname, "jpg", 100);
|
|
if(ret)
|
|
{
|
|
qDebug() << "saveClipImages(): saving image " << localpath+fname << " Successfull";
|
|
|
|
|
|
if (file.copy(localpath + fname, path + fname))
|
|
qDebug() << "saveClipImages(): copying image to " << path + fname << " Successfull";
|
|
else
|
|
{
|
|
qDebug() << "saveClipImages(): copying image to " << path + fname << " Unsuccessfull: reason: " << file.errorString();
|
|
ret = false;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
qDebug() << "saveClipImages(): Saving image " << fname << " Unsuccessfull";
|
|
ret = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!ret)
|
|
{
|
|
//error happend in the complete set of images, so we delete what is already created
|
|
qDebug() << "saveClipImages(): Error happened while saving, remove the saved images!";
|
|
for(int j=0; j< i; j++)
|
|
{
|
|
QString fname = QString("%1-%2.jpg").arg(id_article).arg(j+1);
|
|
file.remove(localpath +fname); //remove it locally
|
|
file.remove(path +fname); //and from file server
|
|
}
|
|
g_clipMutex.unlock();
|
|
return 0;
|
|
}
|
|
|
|
//we also check to see if the image does REALLY exist on that folder
|
|
qDebug() << "saveClipImages(): Checking if the images exist on the server and the images sizes is larger than 30kb";
|
|
for(int i=0; i< list.count(); i++)
|
|
{
|
|
QString fname = path + QString("%1-%2.jpg").arg(id_article).arg(i+1);
|
|
QFileInfo fi(fname);
|
|
if( !fi.exists() || (fi.size() < 20 * 1024))
|
|
{
|
|
qDebug() << "saveClipImages(): Image " << fname << " DOES not exist, or size less than 30 kb: " << file.errorString();
|
|
ret= false;
|
|
break;
|
|
}
|
|
else
|
|
qDebug() << "saveClipImages(): Image " << fname << " exist on the server";
|
|
}
|
|
|
|
//now save the thumbnail to server
|
|
qDebug() << "saveClipImages(): save the thumbnail";
|
|
QString thumbnailName = QString("%1_thumb.jpg").arg(id_article);
|
|
|
|
if(file.exists(localpath+ thumbnailName))
|
|
{
|
|
file.remove(localpath + thumbnailName);
|
|
file.remove(path + thumbnailName);
|
|
}
|
|
|
|
m_thumbnail.save(localpath + thumbnailName, "jpg", 100);
|
|
file.copy(localpath + thumbnailName, path + thumbnailName);
|
|
qDebug() << "saveClipImages(): save the thumbnail DONE";
|
|
|
|
/*
|
|
qDebug() << "saveClipImages(): Trying to open the saved images";
|
|
for(int i=0; i< list.count(); i++)
|
|
{
|
|
QString fname = path + QString("%1-%2.jpg").arg(id_article).arg(i+1);
|
|
QFile file(fname);
|
|
if( !file.open(QFile::ReadOnly) )
|
|
{
|
|
qDebug() << "saveClipImages(): Image " << fname << " DOES not open, reason: " << file.errorString();
|
|
ret= false;
|
|
break;
|
|
}
|
|
else
|
|
qDebug() << "saveClipImages(): Image " << fname << " opens OK";
|
|
file.close();
|
|
}
|
|
*/
|
|
|
|
if(ret)
|
|
{
|
|
Article::updateImagesNumber(m_clipDatabase, id_article, list.count());
|
|
Article::updateStatus(m_clipDatabase, id_article, 2);
|
|
qDebug("saveClipImages(): Everything is OK for article %d, updating the status =2 and images number = %d", id_article, list.count());
|
|
g_clipMutex.unlock();
|
|
return id_article;
|
|
}
|
|
|
|
//if error happens, return to preclip, if pre-clip, or delete it from clipping
|
|
Article::updateImagesNumber(m_clipDatabase, id_article, 0);
|
|
qDebug("saveClipImages(): Error happend for article %d. roll back to original values", id_article);
|
|
g_clipMutex.unlock();
|
|
return 0;
|
|
}
|
|
|
|
bool ClippingStation::saveClipImagesToFtpServer (QString ¤tIssue, int &id_article, QList<QImage> &list, bool fromPreclip, QSqlDatabase &database)
|
|
{
|
|
QString path = SystemConfiguration::clippingsPath();
|
|
|
|
QStringList dateSplit = currentIssue.split("-");
|
|
path = path + QString("%1/%2/%3/").arg(dateSplit[0], 4, QChar('0')).arg(dateSplit[1], 2, QChar('0')).arg(dateSplit[2], 2, QChar('0'));
|
|
|
|
CURL *curlhandle = NULL; //the libcurl easy handle
|
|
|
|
path = QString("ftp://%1:%2@%3/").arg(m_username).arg(m_password).arg(m_address) + path;
|
|
|
|
curl_global_init(CURL_GLOBAL_ALL); //initate it
|
|
curlhandle = curl_easy_init();
|
|
|
|
bool ret = true;
|
|
char str[255];
|
|
saveClipImagesToFtpServerErrorMsg = "";
|
|
|
|
for(int i=0; i< list.count(); i++)
|
|
{
|
|
QString tmpfilename = QString("%1-%2.jpg").arg(id_article).arg(i+1);
|
|
QString filename = path + tmpfilename;
|
|
|
|
if( list[i].save(tmpfilename, "jpg", 100) )
|
|
{
|
|
ret = upload(curlhandle, filename.toLocal8Bit(), tmpfilename.toLocal8Bit(), 0, 3, str);
|
|
if(!ret)
|
|
{
|
|
qDebug() << "saveClipImagesToFtpServer(): Error uploading image " << filename.toLocal8Bit() << ": " << str;
|
|
QFile::remove(tmpfilename);
|
|
saveClipImagesToFtpServerErrorMsg = str;
|
|
ret = false;
|
|
break;
|
|
}
|
|
|
|
QFile::remove(tmpfilename);
|
|
}
|
|
else
|
|
{
|
|
ret = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//now save the thumbnail image as well
|
|
{
|
|
QString tmpfilename = QString("%1_thumb.jpg").arg(id_article);
|
|
QString filename = path + tmpfilename;
|
|
|
|
if( m_thumbnail.save(tmpfilename, "jpg", 100) )
|
|
{
|
|
ret = upload(curlhandle, filename.toLocal8Bit(), tmpfilename.toLocal8Bit(), 0, 3, str);
|
|
if(!ret)
|
|
{
|
|
qDebug() << "saveClipImagesToFtpServer(): Error uploading image " << filename.toLocal8Bit() << ": " << str;
|
|
QFile::remove(tmpfilename);
|
|
saveClipImagesToFtpServerErrorMsg = str;
|
|
//ret = false;
|
|
//break;
|
|
}
|
|
|
|
QFile::remove(tmpfilename);
|
|
}
|
|
}
|
|
|
|
if(ret)
|
|
return true;
|
|
|
|
if(fromPreclip)
|
|
Article::updateStatus(database, id_article, 1);
|
|
else
|
|
Article::deleteArticle(database, id_article);
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ClippingStation::addTextToClip(int id_article, QList<ImageCutout*> &list, QSqlDatabase &database, bool isArabic)
|
|
{
|
|
//first, get the words from database, and then get the text and add it to database.
|
|
qDebug() << "addTextToClip()";
|
|
|
|
QStringList pages = ImageCutout::fullPages(list);
|
|
|
|
QHash<QString, QList<WordCoordinates> > wcHash;
|
|
|
|
for(int i=0; i< pages.count(); i++)
|
|
{
|
|
QList<WordCoordinates> wc = loadImageText(pages[i], database);
|
|
qDebug("word counts = %d", wc.count());
|
|
wcHash.insert(pages[i], wc);
|
|
}
|
|
|
|
QString headline = "";
|
|
//now get coordinates of the text
|
|
QString text = "";
|
|
for(int i=0; i< list.count(); i++)
|
|
{
|
|
QString pagename = list[i]->pageName();
|
|
QString t = getTextFromCutout( list[i]->boundingRect().toRect(), wcHash.value(pagename) );
|
|
text+= t + " ";
|
|
if(list[i]->areaType() == TITLE)
|
|
headline += t + " ";
|
|
}
|
|
|
|
qDebug() << "addTextToClip() headline is : " << headline;
|
|
qDebug() << "addTextToClip() Text is : " << text;
|
|
|
|
//now add the text to clip.
|
|
Article::updateText(database, id_article, text);
|
|
|
|
if(headline.trimmed().isEmpty())
|
|
{
|
|
int index = text.indexOf("\n");
|
|
if(index > -1 && index < text.length())
|
|
headline = text.left(index);
|
|
else
|
|
headline = text.left(100).trimmed();
|
|
|
|
qDebug() << "addTextToClip() new headline is : " << headline;
|
|
}
|
|
|
|
if(!headline.trimmed().isEmpty())
|
|
Article::updateHeadline(database, id_article, headline, isArabic);
|
|
|
|
qDebug() << "end of addTextToClip()";
|
|
return true;
|
|
}
|
|
|
|
QString ClippingStation::getTextFromCutout( QRect rect, QList<WordCoordinates> wc )
|
|
{
|
|
QStringList words;
|
|
|
|
for(int i=0; i<wc.count(); i++)
|
|
{
|
|
Coordinates crd = wc[i].coordinates();
|
|
QPointF pt1(crd.left(), crd.top());
|
|
QPointF pt2(crd.right(), crd.bottom());
|
|
|
|
QRectF rec(pt1, pt2);
|
|
|
|
if( rect.contains( rec.toRect() ) )
|
|
words.append(wc[i].word());
|
|
}
|
|
return words.join(" ");
|
|
}
|
|
|
|
void ClippingStation::saveClipImagesToFtpServerWatcherFinished()
|
|
{
|
|
bool t = m_saveClipImagesToFtpServerWatcher.result();
|
|
if(!t) //if error happen, show a message
|
|
QMessageBox::critical(this, tr("Ftp Clipping Error"), tr("Error uploading clipping images to Ftp (%1)").arg(saveClipImagesToFtpServerErrorMsg) );
|
|
}
|
|
|
|
void ClippingStation::saveClipImagesToFileServerWatcherFinished()
|
|
{
|
|
int id = m_saveClipImagesToFileServerWatcher.result();
|
|
if(id == 0) //if error happen, show a message
|
|
QMessageBox::critical(this, tr("Clipping Error"), tr("Error copying clipping images to file server (%1)").arg(saveClipImagesToFtpServerErrorMsg) );
|
|
//else
|
|
// Article::updateStatus(m_masterDatabase, id, 2);
|
|
}
|
|
|
|
void ClippingStation::addTextToClipWatcherFinished()
|
|
{
|
|
|
|
}
|
|
|
|
void ClippingStation::on_rejectButton_clicked()
|
|
{
|
|
//reject the current clip, i.e. set the reject value to 1.
|
|
//m_currentClipId;
|
|
QSqlQuery query(m_masterDatabase);
|
|
|
|
query.prepare("UPDATE article SET reject = 1 where id_article = :id");
|
|
query.bindValue(":id", m_currentClipId);
|
|
|
|
if( query.exec() )
|
|
{
|
|
//the clip is rejected, move it from the list
|
|
m_publication.currentIssue()->deleteArticleFromView(ui->clipsTreeView, m_currentClipId, false);
|
|
drawerResetPages();
|
|
//remove the cutouts
|
|
ui->fullpageView->removeImageCutouts();
|
|
}
|
|
}
|
|
|
|
void ClippingStation::thumbnail()
|
|
{
|
|
//first restore the page to its original size, then take the screenshot
|
|
if ( m_firstPageInClip.isEmpty() )
|
|
{
|
|
if (m_runningMode == PRECLIPPING_MODE ) m_firstPageInClip = m_preclippedLocalImagesList [m_preclippedImageIndex];
|
|
else if (m_runningMode == NORMAL_MODE ) m_firstPageInClip = m_localImagesList [m_imageIndex ];
|
|
else if (m_runningMode == CLIPPING_MODE ) m_firstPageInClip = m_clippedLocalImagesList [m_clippedImageIndex ];
|
|
}
|
|
|
|
QString currentPage;
|
|
if (m_runningMode == PRECLIPPING_MODE ) currentPage = m_preclippedLocalImagesList [m_preclippedImageIndex];
|
|
else if (m_runningMode == NORMAL_MODE ) currentPage = m_localImagesList [m_imageIndex ];
|
|
else if (m_runningMode == CLIPPING_MODE ) currentPage = m_clippedLocalImagesList [m_clippedImageIndex ];
|
|
|
|
if ( m_firstPageInClip == currentPage)
|
|
{
|
|
qreal oldscale = ui->fullpageView->actualSize();
|
|
QImage img = ui->fullpageView->screenShot();
|
|
ui->fullpageView->setScale(oldscale);
|
|
|
|
img = img.scaledToWidth(THUMBNAIL_WIDTH, Qt::SmoothTransformation);
|
|
m_thumbnail = img;
|
|
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(0));
|
|
view->addThumbnail(img);
|
|
}
|
|
}
|
|
|
|
void ClippingStation::createThumbnail()
|
|
{
|
|
thumbnail();
|
|
}
|
|
|
|
qreal ClippingStation::A4Scale()
|
|
{
|
|
int i = ui->stackedDrawerViewWidget->currentIndex();
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
|
|
m_currentA4Scale = view->currentScale();
|
|
|
|
return m_currentA4Scale;
|
|
}
|
|
|
|
void ClippingStation::enableDrawerButtons(bool enable)
|
|
{
|
|
ui->addPageButton ->setEnabled(enable);
|
|
ui->removePageButton ->setEnabled(enable);
|
|
ui->clipButton ->setEnabled(enable);
|
|
ui->rejectButton ->setEnabled(!enable);
|
|
}
|
|
|
|
void ClippingStation::setModifyClipButton(bool modify)
|
|
{
|
|
ui->clipButton->setEnabled(true);
|
|
if(modify)
|
|
ui->clipButton->setText(tr("Modify"));
|
|
else
|
|
ui->clipButton->setText(tr("Clip"));
|
|
}
|
|
|
|
void ClippingStation::setModifyPreclipButton(bool modify)
|
|
{
|
|
if(modify)
|
|
{
|
|
ui->preclipButton->setText(tr("Modify"));
|
|
ui->cancelModifyPreclipButton->setVisible(true);
|
|
}
|
|
else
|
|
{
|
|
ui->preclipButton->setText(tr("Preclip"));
|
|
ui->cancelModifyPreclipButton->setVisible(false);
|
|
}
|
|
}
|
|
|
|
void ClippingStation::cancelModifyPreclip()
|
|
{
|
|
qDebug("cancelModifyPreclip()");
|
|
|
|
setModifyPreclipButton(false);
|
|
loadImage();
|
|
}
|
|
|
|
void ClippingStation::loadFilteredPublication(int index)
|
|
{
|
|
if( index == 0 )
|
|
{
|
|
m_filterMode = NO_FILTER;
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
return;
|
|
}
|
|
else if( index == 1)
|
|
{
|
|
m_filterMode = PRECLIPSONLY_FILTER;
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
|
|
QStringList list = Publication::publicationsWithPreclips(m_slaveDatabase);
|
|
list.insert(0, "");
|
|
|
|
ui->preclippedPublicationComboBox->clear();
|
|
ui->preclippedPublicationComboBox->addItems(list);
|
|
}
|
|
else if(index == 2)
|
|
{
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
}
|
|
else if(index == 3)
|
|
{
|
|
m_filterMode = NO_FILTER;
|
|
m_publication.initalizeViews(ui->issuesTreeView, ui->clipsTreeView);
|
|
|
|
QStringList list = Publication::publicationsWithUndoneIssues(m_slaveDatabase);
|
|
list.insert(0, "");
|
|
|
|
ui->undonePublicationComboBox->clear();
|
|
ui->undonePublicationComboBox->addItems(list);
|
|
}
|
|
}
|
|
|
|
void ClippingStation::loadClippingImages(int clipid)
|
|
{
|
|
qDebug("loadClippingImages()");
|
|
|
|
//get the number of a4 images for this clip, in addition to the path
|
|
QString path = SystemConfiguration::clippingsPath();
|
|
|
|
QStringList dateSplit = m_currentIssueDate.split("-");
|
|
path = path + QString("%1/%2/%3/").arg(dateSplit[0], 4, QChar('0')).arg(dateSplit[1], 2, QChar('0')).arg(dateSplit[2], 2, QChar('0'));
|
|
|
|
CURL *curlhandle = NULL; //the libcurl easy handle
|
|
|
|
if( m_useFtp)
|
|
{
|
|
path = QString("ftp://%1:%2@%3/").arg(m_username).arg(m_password).arg(m_address) + path;
|
|
|
|
curl_global_init(CURL_GLOBAL_ALL); //initate it
|
|
curlhandle = curl_easy_init();
|
|
}
|
|
else
|
|
{
|
|
#ifdef Q_WS_WIN
|
|
path = SystemConfiguration::clippingsWindowsDriveLetter() + path;
|
|
#endif
|
|
}
|
|
|
|
drawerResetPages();
|
|
int count = m_publication.currentIssue()->clip(clipid).imagesNumber(); //get number of clipped images
|
|
char str[255];
|
|
|
|
for(int i=0; i< count -1 ; i++) //add pages
|
|
drawerAddPage(false);
|
|
|
|
for(int i=0; i< count; i++)
|
|
{
|
|
QString tmpfilename = QString("%1-%2.jpg").arg(clipid).arg(i+1);
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
|
|
if(m_useFtp)
|
|
{
|
|
QString file = path+ tmpfilename;
|
|
if (!download(curlhandle, file.toLocal8Bit(), tmpfilename.toLocal8Bit(), 0, 3, str))
|
|
{
|
|
qDebug() << "loadClippingImages(): Error loading image " << file.toLocal8Bit() << ": " << str;
|
|
QMessageBox::critical(this, "error loading clip", QString("Ftp Error (%1) : %2").arg(file).arg(str) );
|
|
}
|
|
else
|
|
{
|
|
view->setPixmap(QPixmap(tmpfilename));
|
|
QFile::remove(tmpfilename);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
QString fname = path+ tmpfilename;
|
|
view->setPixmap(QPixmap(fname));
|
|
}
|
|
}
|
|
|
|
ui->stackedDrawerViewWidget->setCurrentIndex(0);
|
|
updateDrawerPageInformation();
|
|
enableDrawerButtons(false);
|
|
setModifyClipButton(true);
|
|
}
|
|
|
|
int ClippingStation::totalNumberOfCutoutsInDrawer()
|
|
{
|
|
int count = 0;
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
count += view->cutoutsCount();
|
|
}
|
|
return count;
|
|
}
|
|
|
|
QStringList ClippingStation::emptyDrawerPages()
|
|
{
|
|
QStringList pages;
|
|
for (int i=0; i < ui->stackedDrawerViewWidget->count(); i++)
|
|
{
|
|
DrawerView* view = static_cast<DrawerView*>(ui->stackedDrawerViewWidget->widget(i));
|
|
int count = view->cutoutsCount();
|
|
if(count == 0)
|
|
pages.append( QString("%1").arg(i+1) );
|
|
}
|
|
return pages;
|
|
}
|
|
|
|
void ClippingStation::orderCutoutsSelections()
|
|
{
|
|
ui->fullpageView->setOrderMode( ui->orderButton->isChecked() );
|
|
ui->preclipButton->setEnabled( !ui->orderButton->isChecked() );
|
|
ui->autoArrangeButton->setEnabled(!ui->orderButton->isChecked() );
|
|
}
|
|
|
|
void ClippingStation::addMargintoPos(QPointF &pos, bool isfirst)
|
|
{
|
|
int dpi = QApplication::primaryScreen()->logicalDotsPerInchX();
|
|
|
|
MarginValues mv;
|
|
if(isfirst)
|
|
mv = SystemConfiguration::firstPageMargin();
|
|
else
|
|
mv = SystemConfiguration::otherPagesMargin();
|
|
|
|
qreal left = mv.left * dpi / 2.54;
|
|
qreal top = mv.top * dpi / 2.54;
|
|
|
|
pos.setX( pos.x() + left );
|
|
pos.setY( pos.y() + top );
|
|
}
|
|
|
|
void ClippingStation::orderList(QList<ImageCutout*> &cutouts)
|
|
{
|
|
for(int i=0; i< cutouts.count() -1 ; i++)
|
|
{
|
|
int min = i;
|
|
for(int j=i+1 ; j< cutouts.count(); j++)
|
|
{
|
|
if(cutouts[min]->order() > cutouts[j]->order())
|
|
min = j;
|
|
}
|
|
if(min != i)
|
|
cutouts.swapItemsAt(i, min);
|
|
}
|
|
}
|
|
|
|
QSizeF ClippingStation::A4CellSize(bool isfirst)
|
|
{
|
|
// we compute pixels dimensions for the page.
|
|
int dpi = QApplication::primaryScreen()->logicalDotsPerInchX();
|
|
qreal pageWidth = dpi * A4_WIDTH;
|
|
qreal pageHeight = dpi * A4_HEIGHT;
|
|
|
|
MarginValues mv ;
|
|
|
|
if(isfirst)
|
|
mv = SystemConfiguration::firstPageMargin();
|
|
else
|
|
mv = SystemConfiguration::otherPagesMargin();
|
|
|
|
qreal m_top = mv.top * dpi / 2.54;
|
|
qreal m_bottom = mv.bottom * dpi / 2.54;
|
|
qreal m_left = mv.left * dpi / 2.54;
|
|
qreal m_right = mv.right * dpi / 2.54;
|
|
|
|
qreal w = pageWidth - (m_left + m_right);
|
|
qreal h = pageHeight - (m_top + m_bottom);
|
|
|
|
w /= 100.0;
|
|
h /= 100.0;
|
|
|
|
return QSizeF(w, h);
|
|
}
|
|
|
|
bool ClippingStation::calculatePosAndScale(QSizeF cellSize, QImage &img, int type, bool resetarray, QPointF &pos, qreal &scale)
|
|
{
|
|
|
|
#define CELLROWS 100
|
|
#define CELLCOLS 100
|
|
|
|
scale = 1.0;
|
|
|
|
static int cells[CELLROWS][CELLCOLS] = {0};
|
|
|
|
if(resetarray)
|
|
{
|
|
for(int j=0; j< CELLROWS; j++)
|
|
for(int i=0; i<CELLCOLS; i++)
|
|
cells[j][i] = 0;
|
|
}
|
|
|
|
//we try to find an open space with adjacent h and v cells
|
|
qreal minScale = 1.0;
|
|
if(type == BODY)
|
|
minScale = .9;
|
|
else
|
|
minScale = .4;
|
|
|
|
while(scale >= minScale)
|
|
{
|
|
qreal width = img.width() * scale;
|
|
qreal height= img.height()* scale;
|
|
|
|
qreal hw = width / cellSize.width();
|
|
qreal hl = height / cellSize.height();
|
|
|
|
qreal horizentalCells = ceil(hw);
|
|
qreal verticalCells = ceil(hl);
|
|
|
|
bool isArabic = (m_publication.language() == "Arabic");
|
|
|
|
if(isArabic)
|
|
{
|
|
for(int row =CELLROWS-1; row >=0; row--)
|
|
{
|
|
for(int col=0; col <CELLCOLS; col++)
|
|
{
|
|
//appropriate length
|
|
if(cells[row][col] == 0)
|
|
{
|
|
//check if we have the necessary cells to go thru
|
|
bool valid = true;
|
|
for(int i=0; i < verticalCells; i++)
|
|
{
|
|
if(col+i >= CELLCOLS)
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(cells[row][col+i] == 0)
|
|
continue;
|
|
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(!valid)
|
|
continue;
|
|
|
|
for(int i=0; i < horizentalCells; i++)
|
|
{
|
|
if(row+i >= CELLROWS)
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(cells[row+i][col] == 0)
|
|
continue;
|
|
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(!valid)
|
|
continue;
|
|
|
|
//now check the internal cells
|
|
for(int i=0; i<horizentalCells; i++)
|
|
{
|
|
for(int j=0; j < verticalCells; j++)
|
|
{
|
|
if(cells[row+i][col+j] != 0)
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!valid)
|
|
continue;
|
|
|
|
for(int i=0; i<horizentalCells; i++)
|
|
{
|
|
for(int j=0; j < verticalCells; j++)
|
|
cells[row+i][col+j] = 1;
|
|
}
|
|
/*
|
|
qDebug("After the settings of 1's");
|
|
for(int i=0; i<20; i++)
|
|
{
|
|
QString str;
|
|
for(int j=0; j< 20; j++)
|
|
str += QString("%1").arg(cells[i][j]) + " ";
|
|
qDebug() << str.toLocal8Bit();
|
|
}
|
|
qDebug("*****************************************************");
|
|
*/
|
|
|
|
//point would be
|
|
pos.setX(row*cellSize.width() );
|
|
pos.setY(col*cellSize.height());
|
|
|
|
return true;
|
|
|
|
}
|
|
}
|
|
}//end of for
|
|
}
|
|
else //not arabic
|
|
{
|
|
for(int row =0; row < CELLROWS; row++)
|
|
{
|
|
for(int col=0; col <CELLCOLS; col++)
|
|
{
|
|
//appropriate length
|
|
if(cells[row][col] == 0)
|
|
{
|
|
//check if we have the necessary cells to go thru
|
|
bool valid = true;
|
|
for(int i=0; i < verticalCells; i++)
|
|
{
|
|
if(col+i >= CELLCOLS)
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(cells[row][col+i] == 0)
|
|
continue;
|
|
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(!valid)
|
|
continue;
|
|
|
|
for(int i=0; i < horizentalCells; i++)
|
|
{
|
|
if(row+i >= CELLROWS)
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(cells[row+i][col] == 0)
|
|
continue;
|
|
|
|
valid = false;
|
|
break;
|
|
}
|
|
|
|
if(!valid)
|
|
continue;
|
|
|
|
//now check the internal cells
|
|
for(int i=0; i<horizentalCells; i++)
|
|
{
|
|
for(int j=0; j < verticalCells; j++)
|
|
{
|
|
if(cells[row+i][col+j] != 0)
|
|
{
|
|
valid = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!valid)
|
|
continue;
|
|
|
|
for(int i=0; i<horizentalCells; i++)
|
|
{
|
|
for(int j=0; j < verticalCells; j++)
|
|
cells[row+i][col+j] = 1;
|
|
}
|
|
/*
|
|
qDebug("After the settings of 1's");
|
|
for(int i=0; i<20; i++)
|
|
{
|
|
QString str;
|
|
for(int j=0; j< 20; j++)
|
|
str += QString("%1").arg(cells[i][j]) + " ";
|
|
qDebug() << str.toLocal8Bit();
|
|
}
|
|
qDebug("*****************************************************");
|
|
*/
|
|
|
|
//point would be
|
|
pos.setX(row*cellSize.width() );
|
|
pos.setY(col*cellSize.height());
|
|
|
|
return true;
|
|
|
|
}
|
|
}
|
|
}//end of for
|
|
}
|
|
scale -= .02;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ClippingStation::isImageLocked(QString image, int &lockedBy)
|
|
{
|
|
clock_t start = clock();
|
|
|
|
int id_publication = m_publication.id();
|
|
int id_issue = m_publication.currentIssue()->id();
|
|
int id_section = m_publication.currentIssue()->section(m_currentSectionName).id();
|
|
|
|
QFileInfo fi(image);
|
|
QString page_name = fi.fileName();
|
|
|
|
|
|
QSqlQuery query(m_slaveDatabase);
|
|
bool ret = query.exec("LOCK TABLES publication_issue as pub issue_sections as iss section_pages as sec READ");
|
|
|
|
query.prepare("SELECT locked_by FROM publication_issue as pub, issue_sections as iss, section_pages as sec WHERE "
|
|
" pub.id_publication_issue = iss.id_publication_issue AND "
|
|
" iss.id_issue_sections = sec.id_issue_sections AND "
|
|
" pub.id_publication = :id_publication AND "
|
|
" pub.id_issue = :id_issue AND "
|
|
" iss.id_section = :id_section AND "
|
|
" sec.page_name = :page_name");
|
|
|
|
query.bindValue(":id_publication", id_publication);
|
|
query.bindValue(":id_issue", id_issue);
|
|
query.bindValue(":id_section", id_section);
|
|
query.bindValue(":page_name", page_name);
|
|
|
|
if ( !query.exec() )
|
|
{
|
|
qDebug() << "isImageLocked() SQL query Error :" << query.lastError().databaseText().toLocal8Bit();
|
|
qDebug("%d\t%d\t%d", id_publication, id_issue, id_section);
|
|
qDebug() << page_name;
|
|
ret = query.exec("UNLOCK TABLES");
|
|
return false;
|
|
}
|
|
|
|
int user_id = 0;
|
|
if( query.next() )
|
|
user_id = query.value(0).toInt();
|
|
|
|
query.exec("UNLOCK TABLES");
|
|
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
|
|
qDebug("isImageLocked() Time: %f", diff);
|
|
|
|
if(user_id != 0 && user_id != m_user.id() )
|
|
{
|
|
lockedBy = user_id;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ClippingStation::lockImage(QString image)
|
|
{
|
|
clock_t start = clock();
|
|
|
|
unlockImages();
|
|
|
|
int id_publication = m_publication.id();
|
|
int id_issue = m_publication.currentIssue()->id();
|
|
int id_section = m_publication.currentIssue()->section(m_currentSectionName).id();
|
|
int id_user = m_user.id();
|
|
|
|
QFileInfo fi(image);
|
|
QString page_name = fi.fileName();
|
|
|
|
QSqlQuery query(m_slaveDatabase);
|
|
bool ret = query.exec("LOCK TABLES publication_issue AS pub READ, section_pages AS sec WRITE, issue_sections AS iss READ");
|
|
query.prepare("UPDATE publication_issue as pub, issue_sections as iss, section_pages as sec "
|
|
" SET locked_by = :id_user "
|
|
" WHERE "
|
|
" pub.id_publication_issue = iss.id_publication_issue AND "
|
|
" iss.id_issue_sections = sec.id_issue_sections AND "
|
|
" pub.id_publication = :id_publication AND "
|
|
" pub.id_issue = :id_issue AND "
|
|
" iss.id_section = :id_section AND "
|
|
" sec.page_name = :page_name");
|
|
|
|
query.bindValue(":id_publication", id_publication);
|
|
query.bindValue(":id_issue", id_issue);
|
|
query.bindValue(":id_section", id_section);
|
|
query.bindValue(":page_name", page_name);
|
|
query.bindValue(":id_user", id_user);
|
|
|
|
ret = query.exec();
|
|
query.exec("UNLOCK TABLES");
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
|
|
qDebug("lockImage() Time: %f", diff);
|
|
return ret;
|
|
}
|
|
|
|
bool ClippingStation::unlockImages()
|
|
{
|
|
clock_t start = clock();
|
|
int id_user = m_user.id();
|
|
|
|
QSqlQuery query(m_slaveDatabase);
|
|
query.exec("LOCK TABLE section_pages as sec WRITE");
|
|
query.prepare("UPDATE section_pages as sec "
|
|
" SET locked_by = 0 "
|
|
" WHERE "
|
|
" sec.locked_by = :id_user ");
|
|
query.bindValue(":id_user", id_user);
|
|
|
|
bool ret = query.exec();
|
|
query.exec("UNLOCK TABLES");
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
|
|
qDebug("unlockImages() Time: %f", diff);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ClippingStation::getImageId(const QString name)
|
|
{
|
|
QSqlQuery query2(m_slaveDatabase);
|
|
query2.prepare("SELECT section_pages FROM "
|
|
" publication_issue as pub, issue_sections as iss, section_pages as sec "
|
|
" WHERE "
|
|
" pub.id_publication_issue = iss.id_publication_issue AND "
|
|
" iss.id_issue_sections = sec.id_issue_sections AND "
|
|
" pub.id_publication = :id_publication AND "
|
|
" pub.id_issue = :id_issue AND "
|
|
" iss.id_section = :id_section AND "
|
|
" sec.page_name = :page_name");
|
|
|
|
query2.bindValue(":id_publication", m_publication.id());
|
|
query2.bindValue(":id_issue", m_publication.currentIssue()->id() );
|
|
query2.bindValue(":id_section", m_publication.currentIssue()->section(m_currentSectionName).id() );
|
|
query2.bindValue(":page_name", name);
|
|
|
|
if ( !query2.exec() )
|
|
{
|
|
qDebug() << "Error in slave db query " << query2.lastQuery().toLocal8Bit();
|
|
qDebug() << "Error is " << query2.lastError().text();
|
|
return -1;
|
|
}
|
|
int id = 0;
|
|
while(query2.next() )
|
|
id = query2.value(0).toInt();
|
|
|
|
return id;
|
|
}
|
|
|
|
void ClippingStation::loadImageHighlights(int imageId)
|
|
{
|
|
clock_t start = clock();
|
|
|
|
QSqlQuery query(m_ocrDatabase);
|
|
query.prepare("SELECT id_company, coordinates, tag FROM "
|
|
" page_tag_coordinates "
|
|
" WHERE "
|
|
" id_section_pages = :id ");
|
|
|
|
query.bindValue(":id", imageId);
|
|
|
|
if ( !query.exec() )
|
|
{
|
|
qDebug() << "Error in ocr db query " << query.lastQuery().toLocal8Bit();
|
|
qDebug() << "Error is " << query.lastError().text();
|
|
return;
|
|
}
|
|
|
|
QList<TagCoordinates> tagH;
|
|
|
|
qDebug() << "retreive the results of page_tag_coordiantes";
|
|
while( query.next() )
|
|
{
|
|
int tagId = query.value(0).toInt();
|
|
QStringList coor = query.value(1).toString().split(":");
|
|
QStringList crd = coor[0].split(",");
|
|
int top = crd[0].toInt();
|
|
int left = crd[1].toInt();
|
|
|
|
int bottom =crd[2].toInt();
|
|
int right =crd[3].toInt();
|
|
|
|
QString tag = query.value(2).toString();
|
|
|
|
TagCoordinates t(tagId, top, left, bottom, right, tag);
|
|
|
|
for(int i=1; i< coor.count(); i++)
|
|
{
|
|
QStringList crd = coor[i].split(",");
|
|
int top = crd[0].toInt();
|
|
int left = crd[1].toInt();
|
|
|
|
int bottom =crd[2].toInt();
|
|
int right =crd[3].toInt();
|
|
|
|
//QRectF rec(QPointF(left, top), QPointF(right, bottom) );
|
|
//QPolygonF ply(rec);
|
|
//ui->fullpageView->createTagsHighlightes(ply);
|
|
|
|
t.AddCoordinates(top, left, bottom, right);
|
|
}
|
|
tagH.append(t);
|
|
}
|
|
|
|
qDebug() << "End get info from page_tag_coordinates" << Qt::endl;
|
|
|
|
//QTimer::singleShot(100, this, SLOT(addRelatedKeywordsToTag(tagH)));
|
|
|
|
//we add the name to the tags
|
|
/*QSqlQuery query2(m_slaveDatabase);
|
|
query2.prepare("SELECT name_company FROM company AS cm, searchword AS sw "
|
|
" WHERE name_searchword LIKE :name1 AND sw.id_company = cm.id_company AND cm.date_end > NOW() "
|
|
" UNION SELECT name_company FROM company WHERE name_company LIKE :name2 AND date_end > NOW()");
|
|
for(int i=0; i< tagH.count(); i++)
|
|
{
|
|
qDebug() << "Searching for tag: " << tagH[i].tag();
|
|
query2.bindValue(":name1", tagH[i].tag() );
|
|
query2.bindValue(":name2", tagH[i].tag() );
|
|
|
|
if(query2.exec())
|
|
{
|
|
QStringList keywords;
|
|
while(query2.next())
|
|
{
|
|
QString name = query2.value(0).toString();
|
|
qDebug() << "related tag: " << name;
|
|
keywords.append(name);
|
|
}
|
|
qDebug() << "for tag " << tagH[i].tag() << ", the number of related keyword is " << keywords.count();
|
|
tagH[i].setRelatedKeywords(keywords);
|
|
}
|
|
}*/
|
|
|
|
ui->fullpageView->addTagCoordinates(tagH);
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
|
|
qDebug("loadImageHighlights() Time: %f", diff);
|
|
}
|
|
|
|
|
|
void ClippingStation::addRelatedKeywordsToTag(QList<TagCoordinates> &tagH)
|
|
{
|
|
qDebug() << "addRelatedKeywordsToTag()";
|
|
QSqlQuery query2(m_slaveDatabase);
|
|
query2.prepare("SELECT name_company FROM company AS cm, searchword AS sw "
|
|
" WHERE name_searchword LIKE :name1 AND sw.id_company = cm.id_company AND cm.date_end > NOW() "
|
|
" UNION SELECT name_company FROM company WHERE name_company LIKE :name2 AND date_end > NOW()");
|
|
for(int i=0; i< tagH.count(); i++)
|
|
{
|
|
qDebug() << "Searching for tag: " << tagH[i].tag();
|
|
query2.bindValue(":name1", tagH[i].tag() );
|
|
query2.bindValue(":name2", tagH[i].tag() );
|
|
|
|
if(query2.exec())
|
|
{
|
|
QStringList keywords;
|
|
while(query2.next())
|
|
{
|
|
QString name = query2.value(0).toString();
|
|
qDebug() << "related tag: " << name;
|
|
keywords.append(name);
|
|
}
|
|
qDebug() << "for tag " << tagH[i].tag() << ", the number of related keyword is " << keywords.count();
|
|
tagH[i].setRelatedKeywords(keywords);
|
|
}
|
|
}
|
|
ui->fullpageView->addTagCoordinates(tagH);
|
|
|
|
qDebug() << "end of addRelatedKeywordsToTag()";
|
|
}
|
|
|
|
|
|
QList<WordCoordinates> ClippingStation::loadImageText(QString page, QSqlDatabase &database)
|
|
{
|
|
qDebug() << "loadImageText(QString page, QSqlDatabase &database)";
|
|
|
|
clock_t start = clock();
|
|
|
|
QStringList list = page.split("/");
|
|
QString id_issue = list[list.count()-6] + list[list.count()-5]+ list[list.count()-4];
|
|
QString page_name = list[list.count()-1];
|
|
int id_section = list[list.count()-2].toInt();
|
|
int id_publication = list[list.count()-3].toInt();
|
|
|
|
QSqlQuery query(database);
|
|
query.prepare("SELECT section_pages FROM "
|
|
" publication_issue as pub, issue_sections as iss, section_pages as sec "
|
|
" WHERE "
|
|
" pub.id_publication_issue = iss.id_publication_issue AND "
|
|
" iss.id_issue_sections = sec.id_issue_sections AND "
|
|
" pub.id_publication = :id_publication AND "
|
|
" pub.id_issue = :id_issue AND "
|
|
" iss.id_section = :id_section AND "
|
|
" sec.page_name = :page_name");
|
|
|
|
query.bindValue(":id_publication", id_publication);
|
|
query.bindValue(":id_issue", id_issue );
|
|
query.bindValue(":id_section", id_section );
|
|
query.bindValue(":page_name", page_name);
|
|
|
|
int section_pages = 0;
|
|
|
|
QList<WordCoordinates> tagW;
|
|
|
|
if (!query.exec())
|
|
{
|
|
qDebug() << query.lastError().text().toLocal8Bit();
|
|
return tagW;
|
|
}
|
|
|
|
if(query.next())
|
|
section_pages = query.value(0).toInt();
|
|
|
|
QSqlQuery query2(m_ocrDatabase);
|
|
query2.prepare("SELECT word, coordinates FROM "
|
|
" page_word_coordinates"
|
|
" WHERE "
|
|
" id_section_pages = :id "
|
|
" order by id_page_word_coordinates");
|
|
|
|
query2.bindValue(":id", section_pages);
|
|
|
|
|
|
if ( !query2.exec() )
|
|
{
|
|
qDebug() << query2.lastError().text().toLocal8Bit();
|
|
return tagW;
|
|
}
|
|
|
|
while( query2.next() )
|
|
{
|
|
QString word = query2.value(0).toString();
|
|
qDebug() << "word is " << word;
|
|
|
|
QStringList coor = query2.value(1).toString().split(":");
|
|
|
|
QStringList crd = coor[0].split(",");
|
|
int top = crd[0].toInt();
|
|
int left = crd[1].toInt();
|
|
|
|
int bottom =crd[2].toInt();
|
|
int right =crd[3].toInt();
|
|
|
|
WordCoordinates t(word, top, left, bottom, right);
|
|
|
|
tagW.append(t);
|
|
}
|
|
|
|
//ui->fullpageView->addWordCoordinates(tagW);
|
|
|
|
double diff = ( clock() - start ) / (double)CLOCKS_PER_SEC;
|
|
|
|
qDebug("loadImageText() Time: %f", diff);
|
|
return tagW;
|
|
}
|
|
|
|
void ClippingStation::addTagsToTagWrapper(QList<int> &tagIds, QStringList tagCoord, bool removedAndThenAdd)
|
|
{
|
|
QList<Tag> tags = Tag::searchTags(m_slaveDatabase, tagIds);
|
|
|
|
for(int i=0; i< tags.count(); i++)
|
|
{
|
|
if(tags[i].id() == tagIds[i])
|
|
tags[i].setCoordinates(tagCoord[i]);
|
|
}
|
|
|
|
if(removedAndThenAdd)
|
|
m_tagsWrapper.removedOcrTags(tags);
|
|
else
|
|
m_tagsWrapper.appenedOcrTags(tags);
|
|
|
|
m_tagsWrapper.showModel();
|
|
}
|
|
|
|
void ClippingStation::updateSectionPagesStatus()
|
|
{
|
|
|
|
QAbstractItemModel* model = ui->issuesTreeView->model();
|
|
int issuesCount = model->rowCount( QModelIndex() );
|
|
|
|
for(int i=0; i< issuesCount; i++)
|
|
{
|
|
if(m_currentIssueDate.isEmpty())
|
|
return;
|
|
|
|
QString issue = model->index(i, 0, QModelIndex() ).data(Qt::DisplayRole).toString();
|
|
if(issue != m_currentIssueDate) //get current issue
|
|
continue;
|
|
|
|
QModelIndex issueIndex = model->index(i, 0, QModelIndex() );
|
|
|
|
int sectionsCount = model->rowCount(issueIndex);
|
|
for(int j=0; j < sectionsCount; j++)
|
|
{
|
|
//get pages status for this particular section from database.
|
|
//the data is returned as mab (name, status);
|
|
QString section = model->index(j, 0, issueIndex).data(Qt::DisplayRole).toString();
|
|
int sectionId = m_publication.currentIssue()->section(section).id();
|
|
|
|
QHash<QString, QIcon> hash = currentSectionPagesStatus(sectionId);
|
|
|
|
QModelIndex sectionIndex = model->index(j, 0, issueIndex);
|
|
|
|
int pagesCount = model->rowCount(sectionIndex);
|
|
|
|
for(int k=0; k< pagesCount; k++)
|
|
{
|
|
QString pageName = model->index(k, 0, sectionIndex).data(Qt::DisplayRole).toString();
|
|
pageName = QString("%1.jpg").arg(pageName.remove(QRegularExpression("[^\\d]")), 4, QChar('0'));
|
|
|
|
QModelIndex pageIndex = model->index(k, 0, sectionIndex);
|
|
if( hash.find(pageName) != hash.end() )
|
|
model->setData(pageIndex, QVariant(hash[pageName]) , Qt::DecorationRole);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
QHash<QString, QIcon> ClippingStation::currentSectionPagesStatus(int sectionId)
|
|
{
|
|
QHash<QString, QIcon> hash;
|
|
|
|
QSqlQuery query(m_masterDatabase);
|
|
|
|
query.prepare("SELECT id_issue_sections FROM issue_sections, publication_issue "
|
|
"WHERE publication_issue.id_publication_issue = issue_sections.id_publication_issue AND "
|
|
"id_publication = :id_publication AND issue_date = :issue_date AND id_section = :id_section");
|
|
query.bindValue(":id_publication", m_publication.id() );
|
|
query.bindValue(":issue_date", m_publication.currentIssue()->date() );
|
|
query.bindValue(":id_section", sectionId);
|
|
|
|
if(! query.exec() )
|
|
return hash;
|
|
|
|
int id_issue_sections = 0;
|
|
if( query.next())
|
|
id_issue_sections = query.value(0).toInt();
|
|
|
|
query.exec("LOCK TABLE section_pages READ");
|
|
|
|
query.prepare("SELECT page_name, status FROM section_pages "
|
|
"WHERE id_issue_sections = :id_issue_sections ORDER BY page_name");
|
|
query.bindValue(":id_issue_sections", id_issue_sections);
|
|
|
|
if ( !query.exec() )
|
|
{
|
|
query.exec("UNLOCK TABLES");
|
|
return hash;
|
|
}
|
|
|
|
|
|
while ( query.next() )
|
|
{
|
|
QString filename = query.value(0).toString();
|
|
int status = query.value(1).toInt();
|
|
QIcon icon;
|
|
|
|
if(status < 1) //not processed
|
|
icon.addFile(":/icons/no_icon.png");
|
|
else if (status == 1 ) //waiting to be processed
|
|
icon.addFile(":/icons/gray_circle.png");
|
|
else if (status == 2 ) //being procssed
|
|
icon.addFile(":/icons/yellow_circle.png");
|
|
else //finished processing
|
|
icon.addFile(":/icons/green_circle.png");
|
|
|
|
hash.insert(filename, icon);
|
|
}
|
|
|
|
query.exec("UNLOCK TABLES");
|
|
|
|
return hash;
|
|
}
|
|
|
|
void ClippingStation::filterPublications()
|
|
{
|
|
if(m_searchPublicationsDlg.exec() == QDialog::Accepted )
|
|
{
|
|
//get the values from the
|
|
QString keyword, startDate, endDate, type, country, ocrSearchword, status;
|
|
bool ischecked;
|
|
m_searchPublicationsDlg.get(keyword, ischecked, startDate, endDate, type, country, ocrSearchword, status);
|
|
//now search for the publications that meet those criteria
|
|
int countryId = -1;
|
|
if(!country.isEmpty())
|
|
countryId = m_countriesHash[country];
|
|
|
|
int typeId = -1;
|
|
if(!type.isEmpty())
|
|
{
|
|
if(type.compare("newspaper", Qt::CaseInsensitive) == 0) //NEWSPAPER 1
|
|
typeId = 1;
|
|
else if(type.compare("magazine", Qt::CaseInsensitive) == 0)
|
|
typeId = 2;
|
|
}
|
|
|
|
QStringList list = m_publication.publicationsFiltered(m_slaveDatabase, m_ocrDatabase, keyword, startDate, endDate, typeId, countryId, ocrSearchword, status);
|
|
list.insert(0, "");
|
|
|
|
ui->filteredPublicationComboBox->clear();
|
|
ui->filteredPublicationComboBox->addItems(list);
|
|
}
|
|
}
|
|
|
|
void ClippingStation::setShortcuts()
|
|
{
|
|
if( !m_clipShortcut.isEmpty() )
|
|
ui->actionClip->setShortcut(m_clipShortcut);
|
|
|
|
if( !m_preclipShortcut.isEmpty() )
|
|
ui->actionPreclip->setShortcut(m_preclipShortcut);
|
|
|
|
if( !m_addPageShortcut.isEmpty() )
|
|
ui->actionDrawerAddPage->setShortcut(m_addPageShortcut);
|
|
|
|
if( !m_nextPageShortcut.isEmpty() )
|
|
ui->actionNextPage->setShortcut(m_nextPageShortcut);
|
|
|
|
if( !m_previousPageShortcut.isEmpty() )
|
|
ui->actionPreviousPage->setShortcut(m_previousPageShortcut);
|
|
}
|
|
|
|
|
|
void ClippingStation::pauseTracking()
|
|
{
|
|
if(m_currentPageId <= 0)
|
|
return;
|
|
|
|
if(m_isPaused)
|
|
{
|
|
//resume
|
|
ui->fullpageView->setImageVisibility(true);
|
|
m_trackingTimer.start(1000);
|
|
ui->pauseTrackButton->setText(tr("Pause Tracking"));
|
|
m_isPaused = false;
|
|
}
|
|
else
|
|
{
|
|
ui->fullpageView->setImageVisibility(false);
|
|
m_trackingTimer.stop();
|
|
ui->pauseTrackButton->setText(tr("Resume Tracking"));
|
|
m_isPaused = true;
|
|
}
|
|
}
|
|
|
|
void ClippingStation::updateTrackLabel()
|
|
{
|
|
ui->lcdCounter->showTime(++m_trackingSeconds);
|
|
if((m_trackingSeconds % m_maxTimeLimit) == 0)
|
|
{
|
|
if(!m_isPaused)
|
|
pauseTracking();
|
|
}
|
|
}
|
|
|
|
int ClippingStation::publicationIssueId(int id_publication, QString issue_date)
|
|
{
|
|
QSqlQuery query(m_slaveDatabase);
|
|
query.prepare("SELECT id_publication_issue FROM publication_issue "
|
|
"WHERE id_publication = :id_publication AND issue_date = :issue_date");
|
|
query.bindValue(":id_publication", id_publication);
|
|
query.bindValue(":issue_date", issue_date);
|
|
|
|
if(!query.exec())
|
|
{
|
|
qDebug() << "select id_publication_issue query error: " << query.lastError().text();
|
|
qDebug() << "returning 0";
|
|
return 0;
|
|
}
|
|
|
|
int id_publication_issue = 0;
|
|
|
|
if(query.next())
|
|
{
|
|
id_publication_issue = query.value(0).toInt();
|
|
return id_publication_issue;
|
|
}
|
|
|
|
return id_publication_issue;
|
|
}
|
|
|
|
int ClippingStation::issueSectionsId(int id_publication_issue, int id_section)
|
|
{
|
|
QSqlQuery query(m_slaveDatabase);
|
|
query.prepare("SELECT id_issue_sections FROM issue_sections WHERE "
|
|
"id_publication_issue = :id_publication_issue AND id_section = :id_section");
|
|
query.bindValue(":id_publication_issue", id_publication_issue);
|
|
query.bindValue(":id_section", id_section);
|
|
|
|
if ( !query.exec() )
|
|
{
|
|
qDebug() << "select id_issue_sections query error: " << query.lastError().text();
|
|
qDebug() << "returning 0";
|
|
return 0;
|
|
}
|
|
|
|
int id_issue_sections = 0;
|
|
if( query.next() )
|
|
id_issue_sections = query.value(0).toInt();
|
|
|
|
return id_issue_sections;
|
|
}
|
|
|
|
|
|
QStringList ClippingStation::getRelatedKeywords(QString tag)
|
|
{
|
|
QSqlQuery query2(m_slaveDatabase);
|
|
query2.prepare("SELECT name_company FROM company AS cm, searchword AS sw "
|
|
" WHERE name_searchword LIKE :name1 AND sw.id_company = cm.id_company AND cm.date_end > NOW() "
|
|
" UNION SELECT name_company FROM company WHERE name_company LIKE :name2 AND date_end > NOW()");
|
|
|
|
qDebug() << "Searching for tag: " << tag;
|
|
query2.bindValue(":name1", tag );
|
|
query2.bindValue(":name2", tag );
|
|
|
|
QStringList keywords;
|
|
|
|
if(query2.exec())
|
|
{
|
|
while(query2.next())
|
|
{
|
|
QString name = query2.value(0).toString();
|
|
qDebug() << "related tag: " << name;
|
|
keywords.append(name);
|
|
}
|
|
qDebug() << "for tag " << tag << ", the number of related keyword is " << keywords.count();
|
|
}
|
|
|
|
return keywords;
|
|
}
|
|
|
|
|
|
void ClippingStation::onAppFocusChanged()
|
|
{
|
|
if(m_currentPageId <= 0) //no pages has been opened yet
|
|
return;
|
|
|
|
if(QApplication::focusWidget())
|
|
{
|
|
if(m_isPaused) //if its pause, return without doing anything
|
|
return;
|
|
|
|
ui->fullpageView->setImageVisibility(true);
|
|
m_trackingTimer.start(1000);
|
|
}
|
|
else
|
|
{
|
|
ui->fullpageView->setImageVisibility(false);
|
|
m_trackingTimer.stop();
|
|
}
|
|
}
|