]> gitweb.hamatoma.de Git - reqt/commitdiff
reimgconvert: image processing
authorhama <hama@siduction.net>
Sat, 30 May 2015 16:41:53 +0000 (18:41 +0200)
committerhama <hama@siduction.net>
Sat, 30 May 2015 23:11:13 +0000 (01:11 +0200)
13 files changed:
appl/reimgconvert/about.ui [new file with mode: 0644]
appl/reimgconvert/aboutdialog.cpp [new file with mode: 0644]
appl/reimgconvert/aboutdialog.hpp [new file with mode: 0644]
appl/reimgconvert/aboutdialog.ui [new file with mode: 0644]
appl/reimgconvert/converter.cpp
appl/reimgconvert/converter.hpp
appl/reimgconvert/main.cpp
appl/reimgconvert/mainwindow.cpp
appl/reimgconvert/mainwindow.hpp
appl/reimgconvert/mainwindow.ui
appl/reimgconvert/reimgconvert.pro
base/ReQStringUtil.cpp
base/ReQStringUtil.hpp

diff --git a/appl/reimgconvert/about.ui b/appl/reimgconvert/about.ui
new file mode 100644 (file)
index 0000000..a6d80c5
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDialog</class>
+ <widget class="QDialog" name="AboutDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>225</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>About</string>
+  </property>
+  <widget class="QTextEdit" name="textEdit">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>20</y>
+     <width>351</width>
+     <height>141</height>
+    </rect>
+   </property>
+   <property name="html">
+    <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;ReFind&lt;/span&gt; for searching files in a directory tree&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;This is a program of the project &amp;quot;&lt;span style=&quot; font-weight:600;&quot;&gt;Re&lt;/span&gt;al &lt;span style=&quot; font-weight:600;&quot;&gt;Pub&lt;/span&gt;lic &lt;span style=&quot; font-weight:600;&quot;&gt;Lib&lt;/span&gt;rary&amp;quot;.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Sources are public domain and available under https://github.com/republib&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Implemented in QT (C++) 5.x&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+  </widget>
+  <widget class="QPushButton" name="pushButton">
+   <property name="geometry">
+    <rect>
+     <x>280</x>
+     <y>180</y>
+     <width>93</width>
+     <height>27</height>
+    </rect>
+   </property>
+   <property name="text">
+    <string>&amp;OK</string>
+   </property>
+  </widget>
+  <action name="action_OK">
+   <property name="text">
+    <string>&amp;OK</string>
+   </property>
+  </action>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>action_OK</sender>
+   <signal>triggered()</signal>
+   <receiver>AboutDialog</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>-1</x>
+     <y>-1</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>199</x>
+     <y>112</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/appl/reimgconvert/aboutdialog.cpp b/appl/reimgconvert/aboutdialog.cpp
new file mode 100644 (file)
index 0000000..f6820d4
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+ */
+
+#include "aboutdialog.hpp"
+#include "ui_aboutdialog.h"
+
+AboutDialog::AboutDialog(const QString& version, QWidget *parent) :
+         QDialog(parent), ui(new Ui::AboutDialog){
+   ui->setupUi(this);
+   ui->labelVersion->setText(version);
+}
+
+AboutDialog::~AboutDialog(){
+   delete ui;
+}
diff --git a/appl/reimgconvert/aboutdialog.hpp b/appl/reimgconvert/aboutdialog.hpp
new file mode 100644 (file)
index 0000000..2c8baec
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Licence:
+ * You can use and modify this file without any restriction.
+ * There is no warranty.
+ * You also can use the licence from http://www.wtfpl.net/.
+ * The original sources can be found on https://github.com/republib.
+ */
+
+#ifndef ABOUTDIALOG_HPP
+#define ABOUTDIALOG_HPP
+
+#include <QDialog>
+
+namespace Ui {
+class AboutDialog;
+}
+
+class AboutDialog: public QDialog {
+   Q_OBJECT
+
+public:
+   explicit AboutDialog(const QString& version, QWidget *parent = 0);
+   ~AboutDialog();
+
+private:
+   Ui::AboutDialog *ui;
+};
+
+#endif // ABOUTDIALOG_HPP
diff --git a/appl/reimgconvert/aboutdialog.ui b/appl/reimgconvert/aboutdialog.ui
new file mode 100644 (file)
index 0000000..a4e82da
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AboutDialog</class>
+ <widget class="QDialog" name="AboutDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>423</width>
+    <height>289</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <property name="modal">
+   <bool>true</bool>
+  </property>
+  <widget class="QTextEdit" name="textEdit">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>20</y>
+     <width>381</width>
+     <height>221</height>
+    </rect>
+   </property>
+   <property name="readOnly">
+    <bool>true</bool>
+   </property>
+   <property name="html">
+    <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;ReImgConvert&lt;/span&gt; for converting images to smaller dimensions/size.&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;This is a program of the project&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Re&lt;/span&gt;al &lt;span style=&quot; font-weight:600;&quot;&gt;Pub&lt;/span&gt;lic &lt;span style=&quot; font-weight:600;&quot;&gt;Lib&lt;/span&gt;rary (RePubLib)&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Sources are public domain and available under&lt;/p&gt;
+&lt;p align=&quot;center&quot; style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;a href=&quot;https://github.com/republib&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://github.com/republib&lt;/span&gt;&lt;/a&gt; &lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Implemented in QT (C++) 5.x&lt;/p&gt;
+&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Icons: Mark James, &lt;a href=&quot;http://famfamfam.com&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://famfamfam.com&lt;/span&gt;&lt;/a&gt; &lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+   </property>
+   <property name="acceptRichText">
+    <bool>false</bool>
+   </property>
+   <property name="textInteractionFlags">
+    <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
+   </property>
+  </widget>
+  <widget class="QWidget" name="layoutWidget">
+   <property name="geometry">
+    <rect>
+     <x>20</x>
+     <y>250</y>
+     <width>381</width>
+     <height>29</height>
+    </rect>
+   </property>
+   <layout class="QHBoxLayout" name="horizontalLayout">
+    <item>
+     <widget class="QLabel" name="label">
+      <property name="text">
+       <string>Version:</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QLabel" name="labelVersion">
+      <property name="text">
+       <string>2015.05.00</string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <spacer name="horizontalSpacer">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <property name="sizeHint" stdset="0">
+       <size>
+        <width>40</width>
+        <height>20</height>
+       </size>
+      </property>
+     </spacer>
+    </item>
+    <item>
+     <widget class="QPushButton" name="pushButtonOK">
+      <property name="text">
+       <string>&amp;OK</string>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>pushButtonOK</sender>
+   <signal>clicked()</signal>
+   <receiver>AboutDialog</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>196</x>
+     <y>183</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>199</x>
+     <y>108</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
index a871bafb25eb4a96099a11623fd0378948be5fda..c1faf6126c5733ab51279b7c172e22bead86b061 100644 (file)
@@ -4,11 +4,13 @@
  * There is no warranty.
  * You also can use the licence from http://www.wtfpl.net/.
  * The original sources can be found on https://github.com/republib.
-*/
-
+ */
 
+#include "../../base/rebase.hpp"
 #include "converter.hpp"
 #include "mainwindow.hpp"
+#include <QRegularExpression>
+#include <QRegExp>
 
 /** @mainpage A converter for images.
  *
  *
  * @section install_sec Installation
  *
- * Copy rplshrink and img_conv.pl into a directory inserted in the executable
+ * Copy reimgconvert into a directory inserted in the executable
  * path, e.g. /usr/local/bin and give them the right "executable".
  *
  * @subsection req_sec Requirements
  *
  * <ul>
  * <li>ImageMagick</li>
- * <li>Perl</li>
  * </ul>
  *
  * @section prog_sec Programming Features
@@ -61,7 +62,7 @@
  *
  * <ul>
  * <li>V1.0 Basic version. Predefined (static) values of the combo boxes.
- *      User language is German only.
+ *      User language is English only.
  * </li>
  * </ul>
  *
  * @brief Implements a specific exception for the converter.
  *
  * Will be used on errors.
-*/
+ */
 
 /** @class ConvertLogger converter.hpp "converter.hpp"
  *
  * @brief Implements an abstract base class for logging.
-*/
-
+ */
 
 /** @class Converter converter.hpp "converter.hpp"
  *
@@ -99,6 +99,8 @@
  *
  */
 
+QString sizeToString(qint64 size);
+
 /**
  * @brief Constructor.
  *
  * @param mainWindow        the window. Will be used for output
  */
 Converter::Converter(const QString& directory, const QString& targetDirectory,
-                     int landscapeX, int landscapeY,
-                     int portraitX, int portraitY,
-                     int squareX, int quality,
-                     MainWindow* mainWindow) :
-    m_dir(directory),
-    m_targetDir(targetDirectory.indexOf(QDir::separator()) >= 0
-        ? targetDirectory
-        : directory + QDir::separator() + targetDirectory),
-    m_landscapeWidth(landscapeX),
-    m_landscapeHeight(landscapeY),
-    m_portraitWidth(portraitX),
-    m_portraitHeight(portraitY),
-    m_squareWidth(squareX),
-    m_quality(quality),
-    m_mainWindows(mainWindow),
-    m_script(new QProcess()),
-    m_shouldStop(false)
-{
+   const QString& sourcePattern, const QString& targetType, int landscapeX,
+   int landscapeY, int portraitX, int portraitY, int squareX, int quality,
+   MainWindow* mainWindow) :
+            m_dir(directory),
+            m_targetDir(
+               targetDirectory.indexOf(QDir::separator()) >= 0 ?
+                  targetDirectory :
+                  directory + QDir::separator() + targetDirectory),
+            m_sourcePattern(sourcePattern),
+            m_targetType(targetType),
+            m_landscapeWidth(landscapeX),
+            m_landscapeHeight(landscapeY),
+            m_portraitWidth(portraitX),
+            m_portraitHeight(portraitY),
+            m_squareWidth(squareX),
+            m_quality(targetType == "jpg" ? quality : 0),
+            m_mainWindows(mainWindow),
+            m_shouldStop(false),
+            m_imageInfo(
+               new QRegularExpression(" (PNG|GIF|JPEG) (\\d+)x(\\d+) ")),
+            m_groupWidth(2),
+            m_groupHeight(3){
 }
 
 /**
  * @brief Destructor.
  */
-Converter::~Converter()
-{
-    delete m_script;
+Converter::~Converter(){
+   delete m_imageInfo;
 }
 
 /**
@@ -149,234 +154,291 @@ Converter::~Converter()
  * @param prefix    the string starting the argument
  * @param value     the value of the argument
  */
-void addArg(QStringList& args, const char* prefix, int value)
-{
-    QString arg;
-    arg.sprintf("%s%d", prefix, value);
-    args << arg;
+void addArg(QStringList& args, const char* prefix, int value){
+   QString arg;
+   arg.sprintf("%s%d", prefix, value);
+   args << arg;
 }
 
 /**
- * @brief Builds the arguments of the script call.
+ * @brief Changes the state of the thread.
  *
- * @return  true: OK<br>
- *          false: error occurred
+ * @param state     the new state
+ * @param info      an info about the change
  */
-bool Converter::buildArgs()
-{
-    bool rc = true;
-    m_args.clear();
-    m_args << "-v";
-    if (m_landscapeHeight > 0)
-        addArg(m_args, "-lw", m_landscapeHeight);
-    else if (m_landscapeWidth > 0)
-        addArg(m_args, "-lh", m_landscapeWidth);
-    else
-        rc = error("keine/falsche Maximalangabe beim Breitformat");
-
-    if (m_portraitWidth > 0)
-        addArg(m_args, "-pw", m_portraitWidth);
-    else if (m_portraitHeight > 0)
-        addArg(m_args, "-ph", m_portraitHeight);
-    else
-        rc = error("keine/falsche Maximalangabe beim Hochformat");
-
-    if (m_squareWidth > 0)
-        addArg(m_args, "-sw", m_squareWidth);
-    else
-        rc = error("keine/falsche Maximalangabe beim Hochformat");
-
-    if (m_quality < 10 || m_quality > 100)
-        rc = error("keine/falsche Qualität");
-    else
-        addArg(m_args, "-q", m_quality);
-
-    return rc;
+void Converter::changeState(Converter::State state, const QString& info){
+   m_mainWindows->on_threadStateChanged(state, info);
 }
 
 /**
- * @brief Changes the state of the thread.
+ * Reads the image properties from an image file.
  *
- * @param state     the new state
- * @param info      an info about the change
+ * @param name      filename with path
+ * @param width     OUT: the width of the image
+ * @param height    OUT: the height of the image
+ * @param info      OUT: information of the image
+ * @return          <code>true</code>: success<br>
+ *                  <code>false</code>: cannot retrieve the image data
  */
-void Converter::changeState(Converter::State state, const QString& info)
-{
-    m_mainWindows->on_threadStateChanged(state, info);
+/**
+ * Converts an image into another format.
+ *
+ * @param source    the source filename with path
+ * @param target    the target filename with path
+ * @param width     the old width of the image
+ * @param height    the old height of the image
+ * @param widthNew  the new width of the image
+ * @param heightNew the new height of the image
+ * @param quality   0 or quality in % (only for JPEG targets)
+ */
+void Converter::convert(const QString& source, const QString& target, int width,
+   int height, int widthNew, int heightNew, int quality){
+   QStringList args;
+   // convert -size 100x200 source.png -resize 50x100 target.jpg";
+   args << "-size" << QString::number(width) + "x" + QString::number(height);
+   args << source;
+   if (quality > 0)
+      args << "-quality" << QString::number(quality);
+   args << "-resize"
+      << QString::number(widthNew) + "x" + QString::number(heightNew);
+   args << target;
+   QProcess process;
+   process.start("/usr/bin/convert", args);
+   QByteArray output;
+   while (process.waitForReadyRead()){
+      output = process.readAll();
+   }
+   output = process.readAllStandardError();
+   if (!output.isEmpty())
+      error(output);
+   process.close();
 }
 
 /**
- * @brief Runs the thread's task.
+ * @brief Converts one file.
  *
- * <ul>
- *<li>Makes the target directory (if necessary)</li>
- *<li>Search the images *.png / *.jpg and converts them</li>
- *<ul>
+ * @param source    the file's name with path
+ * @param target    the new filename with path
+ * @param size  the size of the file (in byte)
  */
-void Converter::run()
-{
-    QString msg;
-    int no = 0;
-    try {
-        if (! m_dir.exists())
-            error("Verzeichnis existiert nicht: " + m_dir.absolutePath());
-        if (! m_targetDir.exists()){
-            QString parentName = m_targetDir.path();
-            QString subdir = m_targetDir.dirName();
-            QDir parent(m_targetDir.path());
-            parent.cdUp();
-            parent.mkdir(subdir);
-        }
-        if (! m_targetDir.exists()){
-            error("Kann Zielverzeichnis nicht anlegen: " + m_targetDir.absolutePath());
-        }
-        QStringList names;
-        names.append("*.jpg");
-        names.append("*.JPG");
-        names.append("*.png");
-        names.append("*.PNG");
-        changeState(Converter::STATE_STARTING, "");
-        buildArgs();
-        m_shouldStop = false;
-        QDirIterator it(m_dir.absolutePath(), names);
-        while(it.hasNext()){
-            if (m_shouldStop){
-                log("Abbruch durch Benutzer");
-                break;
+void Converter::convertOneFile(const QString& source, const QString& target,
+   qint64 size){
+   int width = 0;
+   int height = 0;
+   QString info;
+   clock_t start = clock();
+   if (readProperties(source, width, height, info)){
+      bool doConvert = false;
+      int widthNew, heightNew;
+      if (abs(width - height) < 5){
+         // Square format:
+         doConvert = width > m_squareWidth;
+         if (doConvert)
+            widthNew = heightNew = m_squareWidth;
+      }else if (width > height){
+         // Landscape:
+         doConvert = width > m_landscapeWidth || height > m_landscapeHeight;
+         if (doConvert){
+            if (width > m_landscapeWidth && m_landscapeWidth > 0){
+               widthNew = m_landscapeWidth;
+               heightNew = height * m_landscapeWidth / width;
+            }else{
+               heightNew = m_landscapeHeight;
+               widthNew = width * m_landscapeHeight / height;
             }
-            no++;
-            it.next();
-            QString path = it.path();
-            qint64 length = it.fileInfo().size();
-            path += QDir::separator();
-            path += it.fileName();
-            convertOneFile(path, length);
-
-            msg.sprintf("%4d Datei(en) konvertiert", no);
-            changeState(Converter::STATE_SUB_TASK_STOPPED, msg);
-        }
-    } catch(ConverterException exc){
-        log("Abarbeitung wegen Fehlers gestoppt: " + exc.message());
-    }
-    msg.sprintf("%d Datei(en) konvertiert", no);
-    changeState(Converter::STATE_READY, msg);
+         }
+      }else{
+         // Portrait
+         doConvert = width > m_portraitWidth || height > m_portraitHeight;
+         if (doConvert){
+            if (width > m_portraitWidth && m_portraitWidth > 0){
+               widthNew = m_portraitWidth;
+               heightNew = height * m_portraitWidth / width;
+            }else{
+               heightNew = m_portraitHeight;
+               widthNew = width * m_portraitHeight / height;
+            }
+         }
+      }
+      log(
+         source + " " + info + " " + sizeToString(size)
+            + QString(" -> %1x%2 ").arg(widthNew).arg(heightNew));
+      convert(source, target, width, height, widthNew, heightNew, m_quality);
+      struct stat info;
+      if (stat(target.toUtf8().constData(), &info) == 0)
+         m_mainWindows->logAppendLast(sizeToString(info.st_size) + " ");
+   }
+   m_mainWindows->logAppendLast(
+      QString("").sprintf("%.3f sec",
+         double(clock() - start) / CLOCKS_PER_SEC));
 }
 
 /**
- * Reads the image properties from an image file.
+ * @brief Logs an error message.
  *
- * @param name      filename with path
- * @param width     OUT: the width of the image
- * @param height    OUT: the height of the image
- * @param info      OUT: information of the image
+ * @param message   the message to log
+ * @return          <code>false</code>
+ * @throws ConverterException
  */
-void Converter::readProperties(const QString& name, int& width, int& height, QString& info)
-{
-
+bool Converter::error(const QString& message){
+   m_mainWindows->log(message);
+   throw ConverterException(message);
+   return false;
 }
 
 /**
- * @brief Search for the Perl script which make the conversion itself.
+ * @brief Logs a message.
  *
- * @param node  the name of script without path.
- * @return      the full name of the script (with path)
+ * @param message   the message to log
+ * @return          <code>true</code>
  */
-QString findScript(const QString& node)
-{
-    static QString rc;
-    if (rc.isEmpty()){
-
-        QDir dir = QDir::current();
-        QFile scriptFile(dir.filePath(node));
-        if (! scriptFile.exists())
-        {
-            extern char** g_argv;
-            dir.setPath(g_argv[0]);
-            dir.cdUp();
-            scriptFile.setFileName(dir.filePath(node));
-        }
-        if (scriptFile.exists())
-            rc = scriptFile.fileName();
-    }
-    return rc;
+bool Converter::log(const QString& message){
+   printf("%s\n", message.toUtf8().constData());
+   m_mainWindows->log(message);
+   return true;
 }
+
 /**
- * @brief Converts the size into a human readable string.
+ * Reads the image properties using the external program "identify".
  *
- * @param size  the size in bytes
- * @return      the size as human readable string, e.g. "2MiByte"
+ * @param name      the filename with path
+ * @param width     OUT: the width of the image
+ * @param height    OUT: the height of the image
+ * @param info      OUT: an info about the image
+ * @return          <code>true</code>: success
+ *                  <code>false</code>: properties not readable
  */
-QString sizeToString(qint64 size)
-{
-    QString rc;
-    if (size < 10*1024)
-        rc.sprintf("%d Bytes", (int) size);
-    else if (size < qint64(10*1024*1024))
-        rc.sprintf("%d KiBytes", (int) (size / 1024));
-    else if (size < qint64(10*1024*1024)*1024)
-        rc.sprintf("%d MiBytes", (int) (size / 1024 / 1024));
-    else
-        rc.sprintf("%d GiBytes", (int) (size / 1024 / 1024 / 1024));
-    return rc;
+bool Converter::readProperties(const QString& name, int& width, int& height,
+   QString& info){
+   QStringList args;
+   args << name;
+   QProcess process;
+   process.start("/usr/bin/identify", args);
+   QByteArray output;
+   bool rc = false;
+   while (process.waitForReadyRead()){
+      output = process.readAll();
+      QRegularExpressionMatch match = m_imageInfo->match(output);
+      if (!match.hasMatch())
+         error(
+            QObject::tr("I am confused (wrong image data):\n%1\nExpected: %2").arg(
+               output.constData()).arg(m_imageInfo->pattern()));
+      else{
+         width = match.captured(m_groupWidth).toInt();
+         height = match.captured(m_groupHeight).toInt();
+         rc = true;
+         info = QString("%1x%2").arg(width).arg(height);
+         break;
+      }
+   }
+   output = process.readAll();
+   output = process.readAllStandardError();
+   if (!output.isEmpty())
+      error(output);
+   process.close();
+   return rc;
 }
 
 /**
- * @brief Converts one file.
+ * @brief Runs the thread's task.
  *
- * @param file  the file's name
- * @param size  the size of the file (in byte)
+ * <ul>
+ *<li>Makes the target directory (if necessary)</li>
+ *<li>Search the images *.png / *.jpg and converts them</li>
+ *<ul>
  */
-void Converter::convertOneFile(const QString& file, qint64 size)
-{
-    QString node("img_trans.pl");
-    log(file + " " + sizeToString(size));
-    QString script(findScript(node));
-    if (script.isEmpty())
-        error("Script nicht gefunden: " + node);
-    else {
-        QStringList args;
-        args << script << m_args << file << m_targetDir.absolutePath();
-        m_script->start("/usr/bin/perl", args);
-        QByteArray output;
-        while (m_script->waitForReadyRead()){
-            output = m_script->readAll();
-            QList<QByteArray> lines = output.split('\n');
-            QList<QByteArray>::iterator it;
-            for (it = lines.begin(); it != lines.end(); it++){
-                log(*it);
-            }
-        }
-        output = m_script->readAllStandardError();
-        if (!output.isEmpty())
-            error(output);
-        m_script->close();
-    }
+void Converter::run(){
+   QString msg;
+   int no = 0;
+   try{
+      if (!m_dir.exists())
+         error(
+            QObject::tr("Directory does not exist: ") + m_dir.absolutePath());
+      if (!m_targetDir.exists()){
+         QString parentName = m_targetDir.path();
+         QString subdir = m_targetDir.dirName();
+         QDir parent(m_targetDir.path());
+         parent.cdUp();
+         parent.mkdir(subdir);
+      }
+      if (!m_targetDir.exists()){
+         error(
+            QObject::tr("Cannot create the target directory: ")
+               + m_targetDir.absolutePath());
+      }
+      changeState(Converter::STATE_STARTING, "");
+      m_shouldStop = false;
+      QDirIterator it(m_dir.absolutePath());
+      QRegExp regExpr(m_sourcePattern, Qt::CaseInsensitive, QRegExp::Wildcard);
+      while (it.hasNext()){
+         if (m_shouldStop){
+            log(QObject::tr("Canceled by the user"));
+            break;
+         }
+         it.next();
+         if (it.fileInfo().isDir())
+            continue;
+         QString node = it.fileName();
+         if (regExpr.indexIn(node) >= 0){
+            no++;
+            QString path = m_dir.absoluteFilePath(node);
+            qint64 length = it.fileInfo().size();
+            QString nodeTarget = ReQStringUtil::replaceExtension(node,
+               "." + m_targetType);
+            QString target = m_targetDir.absoluteFilePath(nodeTarget);
+            convertOneFile(path, target, length);
+         }
+      }
+      changeState(Converter::STATE_SUB_TASK_STOPPED, msg);
+   } catch (ConverterException exc){
+      log(
+         QObject::tr("Execution stopped because of error(s): ")
+            + exc.message());
+   }
+   msg = QObject::tr("%1 file(s) converted").arg(no);
+   changeState(Converter::STATE_READY, msg);
+   m_mainWindows->switchRun(true);
 }
 
 /**
- * @brief Logs a message.
+ * @brief Search for the Perl script which make the conversion itself.
  *
- * @param message   the message to log
- * @return          <code>true</code>
+ * @param node  the name of script without path.
+ * @return      the full name of the script (with path)
  */
-bool Converter::log(const QString& message)
-{
-    printf ("%s\n", message.toUtf8().constData());
-    m_mainWindows->log(message);
-    return true;
-}
+QString findScript(const QString& node){
+   static QString rc;
+   if (rc.isEmpty()){
 
+      QDir dir = QDir::current();
+      QFile scriptFile(dir.filePath(node));
+      if (!scriptFile.exists()){
+         extern char** g_argv;
+         dir.setPath(g_argv[0]);
+         dir.cdUp();
+         scriptFile.setFileName(dir.filePath(node));
+      }
+      if (scriptFile.exists())
+         rc = scriptFile.fileName();
+   }
+   return rc;
+}
 /**
- * @brief Logs an error message.
+ * @brief Converts the size into a human readable string.
  *
- * @param message   the message to log
- * @return          <code>false</code>
- * @throws ConverterException
+ * @param size  the size in bytes
+ * @return      the size as human readable string, e.g. "2MiByte"
  */
-bool Converter::error(const QString& message)
-{
-    m_mainWindows->log(message);
-    throw ConverterException(message);
-    return false;
+QString sizeToString(qint64 size){
+   QString rc;
+   if (size < 10 * 1024)
+      rc.sprintf("%d Bytes", (int) size);
+   else if (size < qint64(10 * 1024 * 1024))
+      rc.sprintf("%d KiBytes", (int) (size / 1024));
+   else if (size < qint64(10 * 1024 * 1024) * 1024)
+      rc.sprintf("%d MiBytes", (int) (size / 1024 / 1024));
+   else
+      rc.sprintf("%d GiBytes", (int) (size / 1024 / 1024 / 1024));
+   return rc;
 }
 
index e4e71405493ee51e9e6bbed2269b28623b659695..ace17eba642789d60991e6848a9c638b3acda70c 100644 (file)
@@ -4,8 +4,7 @@
  * There is no warranty.
  * You also can use the licence from http://www.wtfpl.net/.
  * The original sources can be found on https://github.com/republib.
-*/
-
+ */
 
 #ifndef CONVERTER_HPP
 #define CONVERTER_HPP
 #include <QThread>
 
 class MainWindow;
-class ConverterException{
+class ConverterException {
 public:
-    ConverterException(const QString& message) : m_message(message)
-    {}
-    const QString& message() const
-    { return m_message; }
+   ConverterException(const QString& message) :
+            m_message(message){
+   }
+   const QString& message() const{
+      return m_message;
+   }
 
 private:
-    QString m_message;
+   QString m_message;
 };
 
-class ConvertLogger{
+class ConvertLogger {
 public:
-    virtual bool log(const QString& message) = 0;
-    virtual bool error(const QString& message) = 0;
+   virtual bool log(const QString& message) = 0;
+   virtual bool error(const QString& message) = 0;
 };
 
-class Converter : public QThread
-{
-    Q_OBJECT
+class Converter: public QThread {
+   Q_OBJECT
 public:
-    enum State {
-        STATE_UNDEF,
-        STATE_STARTING,
-        STATE_SUB_TASK_STOPPED,
-        STATE_READY,
-    };
+   enum State {
+      STATE_UNDEF, STATE_STARTING, STATE_SUB_TASK_STOPPED, STATE_READY,
+   };
 public:
-    Converter(const QString& directory, const QString& targetDirectory,
-              int landscapeX, int landscapey,
-              int portraitX, int portraitY,
-              int squareX, int quality, MainWindow* mainWindows);
-    ~Converter();
+   Converter(const QString& directory, const QString& targetDirectory,
+      const QString& sourcePattern, const QString& targetType, int landscapeX,
+      int landscapey, int portraitX, int portraitY, int squareX, int quality,
+      MainWindow* mainWindows);
+   ~Converter();
 public:
-    bool log(const QString& message);
-    bool error(const QString& message);
-    void run();
-    void stop(){
-        m_shouldStop = true;
-    }
+   bool error(const QString& message);
+   bool log(const QString& message);
+   void run();
+   void stop(){
+      m_shouldStop = true;
+   }
 protected:
-    void readProperties(const QString& name, int &width, int &height, QString &info);
-    void convertOneFile(const QString& name, qint64 size);
-    bool buildArgs();
-    void changeState(State state, const QString& info);
+   bool buildArgs();
+   void changeState(State state, const QString& info);
+   void convert(const QString& source, const QString& target, int width,
+      int height, int widthNew, int heightNew, int quality);
+   void convertOneFile(const QString& source, const QString& target,
+      qint64 size);
+   bool readProperties(const QString& name, int &width, int &height,
+      QString &info);
 private:
-    QDir m_dir;
-    QDir m_targetDir;
-    int m_landscapeWidth;
-    int m_landscapeHeight;
-    int m_portraitWidth;
-    int m_portraitHeight;
-    int m_squareWidth;
-    int m_quality;
-    MainWindow* m_mainWindows;
-    QProcess* m_script;
-    QStringList m_args;
-    bool m_shouldStop;
+   QDir m_dir;
+   QDir m_targetDir;
+   QString m_sourcePattern;
+   QString m_targetType;
+   int m_landscapeWidth;
+   int m_landscapeHeight;
+   int m_portraitWidth;
+   int m_portraitHeight;
+   int m_squareWidth;
+   int m_quality;
+   MainWindow* m_mainWindows;
+   bool m_shouldStop;
+   QRegularExpression* m_imageInfo;
+   int m_groupWidth;
+   int m_groupHeight;
 };
 
-
 #endif // CONVERTER_HPP
index fd619254abe4a0f5b4970d6f2d21f5def0442eb0..6d571f3d49ad791dbe98d364cb75fc8c158b5afc 100644 (file)
@@ -4,18 +4,16 @@
  * There is no warranty.
  * You also can use the licence from http://www.wtfpl.net/.
  * The original sources can be found on https://github.com/republib.
-*/
-
+ */
 
 #include "mainwindow.hpp"
 #include <QApplication>
 char** g_argv;
-int main(int argc, char *argv[])
-{
-    g_argv = argv;
-    QApplication a(argc, argv);
-    MainWindow w;
-    w.show();
+int main(int argc, char *argv[]){
+   g_argv = argv;
+   QApplication a(argc, argv);
+   MainWindow w;
+   w.show();
 
-    return a.exec();
+   return a.exec();
 }
index a8bc2d69e3048096143e56e76287dc55db6834aa..4ffd4af8a975f16e0d817d99a3cf83059071c655 100644 (file)
@@ -4,11 +4,13 @@
  * There is no warranty.
  * You also can use the licence from http://www.wtfpl.net/.
  * The original sources can be found on https://github.com/republib.
-*/
-
+ */
 
 #include "mainwindow.hpp"
 #include "ui_mainwindow.h"
+#include "aboutdialog.hpp"
+
+const QString VERSION("2015.05.31");
 
 /** @class MainWindow mainwindow.hpp "mainwindow.hpp"
  *
  * @param parent        NULL or the parent (who destroys the objects at the end)
  */
 MainWindow::MainWindow(QWidget *parent) :
-    QMainWindow(parent),
-    ui(new Ui::MainWindow),
-    m_converter(NULL)
-{
-    ui->setupUi(this);
-    QStringList defaultX;
-    defaultX.append("*");
-    defaultX.append("1024");
-    defaultX.append("1920");
-    defaultX.append("800");
-    QStringList defaultY;
-    defaultY.append("*");
-    defaultY.append("768");
-    defaultY.append("1050");
-    defaultY.append("600");
-    QStringList quality;
-    quality.append("70");
-    quality.append("85");
-    quality.append("100");
-    QStringList target;
-    target.append("normal");
-    target.append("mini");
-    target.append("1024");
-    target.append("1920");
-    ui->comboLandscapeX->addItems(defaultX);
-    ui->comboLandscapeY->addItems(defaultY);
-    ui->comboPortraitX->addItems(defaultX);
-    ui->comboPortraitY->addItems(defaultY);
-    ui->comboSquareX->addItems(defaultX);
-    ui->comboQuality->addItems(quality);
-    ui->comboTarget->addItems(target);
-    ui->comboLandscapeX->setCurrentText("1024");
-    ui->comboLandscapeY->setCurrentText("*");
-    ui->comboPortraitX->setCurrentText("*");
-    ui->comboPortraitY->setCurrentText("768");
-    ui->comboSquareX->setCurrentText("768");
-    ui->comboQuality->setCurrentText("70");
-    ui->comboTarget->setCurrentText("normal");
-    ui->buttonStop->hide();
+         QMainWindow(parent), ui(new Ui::MainWindow), m_converter(NULL){
+   ui->setupUi(this);
+   switchRun(true);
+   QStringList defaultX;
+   defaultX.append("*");
+   defaultX.append("1024");
+   defaultX.append("1920");
+   defaultX.append("800");
+   QStringList defaultY;
+   defaultY.append("*");
+   defaultY.append("768");
+   defaultY.append("1050");
+   defaultY.append("600");
+   QStringList quality;
+   quality.append("70");
+   quality.append("85");
+   quality.append("100");
+   QStringList target;
+   target.append("normal");
+   target.append("mini");
+   target.append("1024");
+   target.append("1920");
+   ui->comboLandscapeX->addItems(defaultX);
+   ui->comboLandscapeY->addItems(defaultY);
+   ui->comboPortraitX->addItems(defaultX);
+   ui->comboPortraitY->addItems(defaultY);
+   ui->comboSquareX->addItems(defaultX);
+   ui->comboQuality->addItems(quality);
+   ui->comboTarget->addItems(target);
+   ui->comboLandscapeX->setCurrentText("1024");
+   ui->comboLandscapeY->setCurrentText("*");
+   ui->comboPortraitX->setCurrentText("*");
+   ui->comboPortraitY->setCurrentText("768");
+   ui->comboSquareX->setCurrentText("768");
+   ui->comboQuality->setCurrentText("70");
+   ui->comboTarget->setCurrentText("normal");
+   ui->buttonStop->hide();
+
+   connect(ui->actionSelectDestination, SIGNAL(triggered()), this,
+      SLOT(selectDestination()));
+   connect(ui->pushButtonSelectDest, SIGNAL(clicked()), this,
+      SLOT(selectDestination()));
+   connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(about()));
+
+}
+
+/**
+ * Selects the destination directory with a dialog.
+ */
+void MainWindow::selectDestination(){
+   QString dir = QFileDialog::getExistingDirectory(this,
+      tr("Select Destination Directory"), ui->comboTarget->currentText(),
+      QFileDialog::ShowDirsOnly);
+   if (!dir.isEmpty())
+      ui->comboTarget->setCurrentText(dir);
 }
 
 /**
  * @brief Destructor
  */
-MainWindow::~MainWindow()
-{
-    delete ui;
-    delete m_converter;
+MainWindow::~MainWindow(){
+   delete ui;
+   delete m_converter;
+}
+
+/**
+ * Starts the about dialog.
+ */
+void MainWindow::about(){
+   AboutDialog dialog(VERSION);
+   dialog.exec();
 }
 
 /**
@@ -81,31 +106,58 @@ MainWindow::~MainWindow()
  * @param message   the message to log
  * @return          <code>true</code>
  */
-bool MainWindow::log(const QString& message)
-{
-    ui->listWidget->addItem(message);
-    return true;
+bool MainWindow::log(const QString& message){
+   ui->listWidget->insertItem(0, message);
+   return true;
+}
+
+/**
+ * @brief Logs a message
+ *
+ * @param message   the message to log
+ * @return          <code>true</code>
+ */
+bool MainWindow::logAppendLast(const QString& message){
+   QListWidgetItem* item = ui->listWidget->item(0);
+   item->setText(item->text() + " " + message);
+   return true;
+}
+
+/**
+ * Enables/disables the buttons/actions relevant for running.
+ *
+ * @param runActive <code>true</code>: the conversion is possible
+ */
+void MainWindow::switchRun(bool runActive){
+   if (runActive){
+      ui->buttonConvert->show();
+      ui->buttonStop->hide();
+   }else{
+      ui->buttonConvert->hide();
+      ui->buttonStop->show();
+   }
+   ui->actionConvert->setEnabled(runActive);
+   ui->actionStop->setEnabled(not runActive);
 }
 
 /**
  * @brief Handles the button click on "convert".
  */
-void MainWindow::on_buttonConvert_clicked()
-{
-    ui->buttonConvert->hide();
-    ui->buttonStop->show();
-    delete m_converter;
-    m_converter = new Converter(ui->comboSourceDir->currentText(),
-        ui->comboLandscapeX->currentText(),
-        atol(ui->comboLandscapeX->currentText().toLatin1().constData()),
-        atol(ui->comboLandscapeY->currentText().toLatin1().constData()),
-        atol(ui->comboPortraitX->currentText().toLatin1().constData()),
-        atol(ui->comboPortraitY->currentText().toLatin1().constData()),
-        atol(ui->comboSquareX->currentText().toLatin1().constData()),
-        atol(ui->comboQuality->currentText().toLatin1().constData()),
-        this);
-    // start the thread:
-    m_converter->start();
+void MainWindow::on_buttonConvert_clicked(){
+   switchRun(false);
+   delete m_converter;
+   m_converter = new Converter(ui->comboSourceDir->currentText(),
+      ui->comboLandscapeX->currentText(),
+      ui->comboBoxSourcePattern->currentText(),
+      ui->comboBoxDestType->currentText(),
+      atol(ui->comboLandscapeX->currentText().toLatin1().constData()),
+      atol(ui->comboLandscapeY->currentText().toLatin1().constData()),
+      atol(ui->comboPortraitX->currentText().toLatin1().constData()),
+      atol(ui->comboPortraitY->currentText().toLatin1().constData()),
+      atol(ui->comboSquareX->currentText().toLatin1().constData()),
+      atol(ui->comboQuality->currentText().toLatin1().constData()), this);
+   // start the thread:
+   m_converter->start();
 }
 
 /**
@@ -114,32 +166,29 @@ void MainWindow::on_buttonConvert_clicked()
  * @param state     the new state of the thread
  * @param info      info about the new state. Not used
  */
-void MainWindow::on_threadStateChanged(Converter::State state,
-                                       const QString&)
-{
-    switch(state){
-    case Converter::STATE_READY:
-        ui->buttonConvert->show();
-        ui->buttonStop->hide();
-        //ui->statusBar->showMessage(info);
-        break;
-    case Converter::STATE_SUB_TASK_STOPPED:
-        //ui->statusBar->showMessage(info);
-        break;
-    case Converter::STATE_STARTING:
-    default:
-        break;
-    }
+void MainWindow::on_threadStateChanged(Converter::State state, const QString&){
+   switch (state) {
+   case Converter::STATE_READY:
+      ui->buttonConvert->show();
+      ui->buttonStop->hide();
+      //ui->statusBar->showMessage(info);
+      break;
+   case Converter::STATE_SUB_TASK_STOPPED:
+      //ui->statusBar->showMessage(info);
+      break;
+   case Converter::STATE_STARTING:
+   default:
+      break;
+   }
 
 }
 /**
  * @brief Handles the click on the button "stop".
  */
-void MainWindow::on_buttonStop_clicked()
-{
-    m_converter->stop();
-    ui->buttonConvert->show();
-    ui->buttonStop->hide();
+void MainWindow::on_buttonStop_clicked(){
+   m_converter->stop();
+   ui->buttonConvert->show();
+   ui->buttonStop->hide();
 }
 
 /**
@@ -148,15 +197,13 @@ void MainWindow::on_buttonStop_clicked()
  * Shows a selection dialog for directories and sets the source directory
  * onto the selected directory.
  */
-void MainWindow::on_buttonFileSelect_clicked()
-{
-    QFileDialog selection;
-    selection.setFileMode(QFileDialog::DirectoryOnly);
-    QString dir = ui->comboSourceDir->currentText();
-    if (! dir.isEmpty())
-        selection.setDirectory(dir);
-    if (selection.exec())
-        ui->comboSourceDir->setCurrentText(selection.selectedFiles().at(0));
+void MainWindow::on_buttonFileSelect_clicked(){
+   QFileDialog selection;
+   selection.setFileMode(QFileDialog::DirectoryOnly);
+   QString dir = ui->comboSourceDir->currentText();
+   if (!dir.isEmpty())
+      selection.setDirectory(dir);
+   if (selection.exec())
+      ui->comboSourceDir->setCurrentText(selection.selectedFiles().at(0));
 }
 
-
index 66e1ee596348a14b67bd9e001a030182ec29df80..43f957f42748474c0c300d592dd7834e5958f09b 100644 (file)
@@ -4,8 +4,7 @@
  * There is no warranty.
  * You also can use the licence from http://www.wtfpl.net/.
  * The original sources can be found on https://github.com/republib.
-*/
-
+ */
 
 #ifndef MAINWINDOW_HPP
 #define MAINWINDOW_HPP
@@ -18,30 +17,30 @@ namespace Ui {
 class MainWindow;
 }
 
-class MainWindow : public QMainWindow, public ConvertLogger
-{
-    Q_OBJECT
+class MainWindow: public QMainWindow, public ConvertLogger {
+   Q_OBJECT
 
 public:
-    explicit MainWindow(QWidget *parent = 0);
-    ~MainWindow();
+   explicit MainWindow(QWidget *parent = 0);
+   ~MainWindow();
 
 public:
-    bool log(const QString& message);
-    bool error(const QString& message){
-        log("+++ " + message); return false;
-    }
-private slots:
-    void on_buttonFileSelect_clicked();
-
-    void on_buttonStop_clicked();
-
-    void on_buttonConvert_clicked();
-public slots:
-    void on_threadStateChanged(Converter::State state, const QString& info);
+   bool error(const QString& message){
+      log("+++ " + message);
+      return false;
+   }
+   bool log(const QString& message);
+   bool logAppendLast(const QString& message);
+   void switchRun(bool runActive);private slots:
+   void about();
+   void on_buttonFileSelect_clicked();
+   void on_buttonStop_clicked();
+   void on_buttonConvert_clicked();
+   void selectDestination();public slots:
+   void on_threadStateChanged(Converter::State state, const QString& info);
 private:
-    Ui::MainWindow *ui;
-    Converter* m_converter;
+   Ui::MainWindow *ui;
+   Converter* m_converter;
 };
 
 #endif // MAINWINDOW_HPP
index ccfc44ee690dcc63ac7526fac6ee8fa7cfbf2f09..34b0e9b3b522d05c6e149a9508c7be0adafebf5f 100644 (file)
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>735</width>
-    <height>532</height>
+    <width>772</width>
+    <height>556</height>
    </rect>
   </property>
   <property name="minimumSize">
@@ -23,7 +23,7 @@
    <layout class="QVBoxLayout" name="verticalLayout_4">
     <item>
      <widget class="QWidget" name="widget" native="true">
-      <layout class="QVBoxLayout" name="verticalLayout_3">
+      <layout class="QVBoxLayout" name="verticalLayout">
        <item>
         <layout class="QHBoxLayout" name="horizontalLayout_5">
          <item>
              </widget>
             </widget>
            </item>
+           <item>
+            <spacer name="horizontalSpacer">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
            <item>
             <widget class="QGroupBox" name="groupBox_2">
              <property name="minimumSize">
              </widget>
             </widget>
            </item>
+           <item>
+            <spacer name="horizontalSpacer_2">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
            <item>
             <widget class="QGroupBox" name="groupBox_3">
              <property name="minimumSize">
            </item>
           </layout>
          </item>
-         <item>
-          <spacer name="horizontalSpacer_2">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
         </layout>
        </item>
        <item>
          <property name="title">
           <string>Others:</string>
          </property>
-         <widget class="QPushButton" name="pushButtonSelectDest">
-          <property name="geometry">
-           <rect>
-            <x>640</x>
-            <y>70</y>
-            <width>51</width>
-            <height>27</height>
-           </rect>
-          </property>
-          <property name="text">
-           <string>...</string>
-          </property>
-         </widget>
-         <widget class="QWidget" name="layoutWidget3">
-          <property name="geometry">
-           <rect>
-            <x>0</x>
-            <y>30</y>
-            <width>221</width>
-            <height>28</height>
-           </rect>
-          </property>
-          <layout class="QFormLayout" name="formLayout_3">
-           <item row="0" column="0">
-            <widget class="QLabel" name="label_6">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Quality (%)</string>
-             </property>
-            </widget>
-           </item>
-           <item row="0" column="1">
-            <widget class="QComboBox" name="comboQuality">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="editable">
-              <bool>true</bool>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-         <widget class="QWidget" name="layoutWidget4">
-          <property name="geometry">
-           <rect>
-            <x>0</x>
-            <y>70</y>
-            <width>631</width>
-            <height>28</height>
-           </rect>
-          </property>
-          <layout class="QFormLayout" name="formLayout_4">
-           <item row="0" column="0">
-            <widget class="QLabel" name="label_7">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Destination: </string>
-             </property>
-            </widget>
-           </item>
-           <item row="0" column="1">
-            <widget class="QComboBox" name="comboTarget">
-             <property name="editable">
-              <bool>true</bool>
-             </property>
-             <property name="currentText">
-              <string/>
-             </property>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-         <widget class="QWidget" name="layoutWidget5">
-          <property name="geometry">
-           <rect>
-            <x>0</x>
-            <y>110</y>
-            <width>631</width>
-            <height>28</height>
-           </rect>
-          </property>
-          <layout class="QHBoxLayout" name="horizontalLayout_4">
-           <item>
-            <widget class="QLabel" name="label_2">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Template:</string>
-             </property>
-            </widget>
-           </item>
-           <item>
-            <widget class="QComboBox" name="comboBox">
-             <item>
-              <property name="text">
-               <string>Website: 1024x768</string>
+         <layout class="QVBoxLayout" name="verticalLayout_3">
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_7">
+            <item>
+             <layout class="QFormLayout" name="formLayout_3">
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_6">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>100</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>Quality (%)</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="QComboBox" name="comboQuality">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>100</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="editable">
+                 <bool>true</bool>
+                </property>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_4">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
               </property>
-             </item>
-             <item>
-              <property name="text">
-               <string>Website II: 800x600</string>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
               </property>
-             </item>
-             <item>
-              <property name="text">
-               <string>Photo: 2048x1536</string>
+             </spacer>
+            </item>
+            <item>
+             <layout class="QFormLayout" name="formLayout_5">
+              <property name="fieldGrowthPolicy">
+               <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
               </property>
-             </item>
-             <item>
-              <property name="text">
-               <string>Photo II: 3072x2304</string>
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_10">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>100</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>File Pattern:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="QComboBox" name="comboBoxSourcePattern">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>100</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="toolTip">
+                 <string>A pattern of the source files with wildcards '*' (anything) and '?' (exact one char)</string>
+                </property>
+                <property name="editable">
+                 <bool>true</bool>
+                </property>
+                <item>
+                 <property name="text">
+                  <string notr="true">*.jpg</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string notr="true">*.png</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>*.gif</string>
+                 </property>
+                </item>
+               </widget>
+              </item>
+             </layout>
+            </item>
+            <item>
+             <spacer name="horizontalSpacer_3">
+              <property name="orientation">
+               <enum>Qt::Horizontal</enum>
               </property>
-             </item>
-             <item>
-              <property name="text">
-               <string>Midi: 600x400</string>
+              <property name="sizeHint" stdset="0">
+               <size>
+                <width>40</width>
+                <height>20</height>
+               </size>
               </property>
-             </item>
-             <item>
-              <property name="text">
-               <string>Mini: 150x100</string>
+             </spacer>
+            </item>
+            <item>
+             <layout class="QFormLayout" name="formLayout_6">
+              <item row="0" column="0">
+               <widget class="QLabel" name="label_11">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>100</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>Dest. Type:</string>
+                </property>
+               </widget>
+              </item>
+              <item row="0" column="1">
+               <widget class="QComboBox" name="comboBoxDestType">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>100</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <item>
+                 <property name="text">
+                  <string notr="true">jpg</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string notr="true">png</string>
+                 </property>
+                </item>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_6">
+            <item>
+             <widget class="QLabel" name="label_7">
+              <property name="minimumSize">
+               <size>
+                <width>100</width>
+                <height>0</height>
+               </size>
               </property>
-             </item>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-         <widget class="QWidget" name="layoutWidget6">
-          <property name="geometry">
-           <rect>
-            <x>240</x>
-            <y>30</y>
-            <width>209</width>
-            <height>28</height>
-           </rect>
-          </property>
-          <layout class="QFormLayout" name="formLayout_5">
-           <item row="0" column="0">
-            <widget class="QLabel" name="label_10">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Source Type:</string>
-             </property>
-            </widget>
-           </item>
-           <item row="0" column="1">
-            <widget class="QComboBox" name="comboBoxSourceType">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="editable">
-              <bool>true</bool>
-             </property>
-             <item>
-              <property name="text">
-               <string notr="true">jpg</string>
+              <property name="maximumSize">
+               <size>
+                <width>100</width>
+                <height>16777215</height>
+               </size>
               </property>
-             </item>
-             <item>
               <property name="text">
-               <string notr="true">png</string>
+               <string>Destination: </string>
               </property>
-             </item>
-             <item>
-              <property name="text">
-               <string>gif</string>
+             </widget>
+            </item>
+            <item>
+             <widget class="QComboBox" name="comboTarget">
+              <property name="editable">
+               <bool>true</bool>
               </property>
-             </item>
-            </widget>
-           </item>
-          </layout>
-         </widget>
-         <widget class="QWidget" name="layoutWidget7">
-          <property name="geometry">
-           <rect>
-            <x>480</x>
-            <y>30</y>
-            <width>211</width>
-            <height>28</height>
-           </rect>
-          </property>
-          <layout class="QFormLayout" name="formLayout_6">
-           <item row="0" column="0">
-            <widget class="QLabel" name="label_11">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <property name="text">
-              <string>Dest. Type:</string>
-             </property>
-            </widget>
-           </item>
-           <item row="0" column="1">
-            <widget class="QComboBox" name="comboBoxDestType">
-             <property name="minimumSize">
-              <size>
-               <width>100</width>
-               <height>0</height>
-              </size>
-             </property>
-             <property name="maximumSize">
-              <size>
-               <width>100</width>
-               <height>16777215</height>
-              </size>
-             </property>
-             <item>
-              <property name="text">
-               <string notr="true">jpg</string>
+              <property name="currentText">
+               <string/>
+              </property>
+             </widget>
+            </item>
+            <item>
+             <widget class="QPushButton" name="pushButtonSelectDest">
+              <property name="minimumSize">
+               <size>
+                <width>50</width>
+                <height>0</height>
+               </size>
+              </property>
+              <property name="maximumSize">
+               <size>
+                <width>50</width>
+                <height>16777215</height>
+               </size>
               </property>
-             </item>
-             <item>
               <property name="text">
-               <string notr="true">png</string>
+               <string>...</string>
               </property>
-             </item>
-            </widget>
-           </item>
-          </layout>
-         </widget>
+             </widget>
+            </item>
+           </layout>
+          </item>
+          <item>
+           <layout class="QHBoxLayout" name="horizontalLayout_8">
+            <item>
+             <layout class="QHBoxLayout" name="horizontalLayout_4">
+              <item>
+               <widget class="QLabel" name="label_2">
+                <property name="minimumSize">
+                 <size>
+                  <width>100</width>
+                  <height>0</height>
+                 </size>
+                </property>
+                <property name="maximumSize">
+                 <size>
+                  <width>100</width>
+                  <height>16777215</height>
+                 </size>
+                </property>
+                <property name="text">
+                 <string>Template:</string>
+                </property>
+               </widget>
+              </item>
+              <item>
+               <widget class="QComboBox" name="comboBox">
+                <item>
+                 <property name="text">
+                  <string>Website: 1024x768</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>Website II: 800x600</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>Photo: 2048x1536</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>Photo II: 3072x2304</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>Midi: 600x400</string>
+                 </property>
+                </item>
+                <item>
+                 <property name="text">
+                  <string>Mini: 150x100</string>
+                 </property>
+                </item>
+               </widget>
+              </item>
+             </layout>
+            </item>
+           </layout>
+          </item>
+         </layout>
         </widget>
        </item>
        <item>
-        <layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0">
+        <layout class="QHBoxLayout" name="horizontalLayout_2">
          <item>
           <layout class="QVBoxLayout" name="verticalLayout_2">
            <item>
           </layout>
          </item>
          <item>
-          <spacer name="horizontalSpacer">
-           <property name="orientation">
-            <enum>Qt::Horizontal</enum>
-           </property>
-           <property name="sizeHint" stdset="0">
-            <size>
-             <width>40</width>
-             <height>20</height>
-            </size>
-           </property>
-          </spacer>
-         </item>
-         <item>
-          <layout class="QVBoxLayout" name="verticalLayout">
+          <layout class="QVBoxLayout" name="verticalLayout_5">
+           <item>
+            <spacer name="verticalSpacer">
+             <property name="orientation">
+              <enum>Qt::Vertical</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>20</width>
+               <height>40</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
            <item>
             <widget class="QPushButton" name="buttonConvert">
              <property name="minimumSize">
     <rect>
      <x>0</x>
      <y>0</y>
-     <width>735</width>
+     <width>772</width>
      <height>23</height>
     </rect>
    </property>
    <slot>close()</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>367</x>
-     <y>265</y>
+     <x>-1</x>
+     <y>-1</y>
     </hint>
     <hint type="destinationlabel">
      <x>367</x>
index 03d68734ebd1add0fa4a2af97cf28f0af2349890..075cbef3ada49d841884ef0838d9cc9422299d11 100644 (file)
@@ -11,17 +11,24 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 TARGET = reimgconvert
 TEMPLATE = app
 
+INCLUDEPATH = ../.. /usr/include/c++/4.9
 
 SOURCES += main.cpp\
-                 mainwindow.cpp \
-        converter.cpp
+        ../../base/ReException.cpp \
+        ../../base/ReQStringUtil.cpp \
+        ../../base/ReLogger.cpp \
+        mainwindow.cpp \
+        converter.cpp \
+    aboutdialog.cpp
 
 HEADERS  += mainwindow.hpp \
-        converter.hpp
+        converter.hpp \
+    aboutdialog.hpp
 
-FORMS    += mainwindow.ui
+FORMS    += mainwindow.ui \
+    aboutdialog.ui
 
 RESOURCES += \
-    reimgconvert.qrc
+        reimgconvert.qrc
 
 OTHER_FILES +=
index 1bc55da227c4a4a01bb3c68dca80c061aff805ad..8fd5025a6b58807f0850f18aa3f80bd2279af380 100644 (file)
@@ -55,15 +55,20 @@ QString& ReQStringUtil::ensureLastChar(QString& value, QChar lastChar){
  */
 ReString ReQStringUtil::extensionOf(const ReString& filename){
    QString rc;
-
    int index = filename.lastIndexOf('.');
+   int index2 = 0;
    if (index > 0){
-      int index2 = filename.lastIndexOf('/');
-      if (index2 < index){
-#if defined WIN32
+      index2 = filename.lastIndexOf('/');
+      if (index2 >= 0){
+          if (index > index2)
+              rc = filename.mid(index);
+      } else {
+#if defined __linux__
+          rc = filename.mid(index);
+#elif defined WIN32
          index2 = filename.lastIndexOf('\\');
-         if (index2 < index)
-         rc = filename.mid(index);
+         if (index2 < 0 || index > index2)
+             rc = filename.mid(index);
 #endif
       }
    }
@@ -413,6 +418,24 @@ QString ReQStringUtil::pathAppend(const QString& base, const QString& path){
    return rc;
 }
 
+/**
+ * Replaces the file extension of a filename.
+ *
+ * @param path  the filename to change
+ * @param ext   the new file extension, e.g. ".txt"
+ * @return      path with a new file extension
+ */
+
+QString ReQStringUtil::replaceExtension(const QString& path, const QString& ext)
+{
+    QString oldExt = extensionOf(path);
+    QString rc;
+    if (oldExt.isEmpty())
+        rc = path + ext;
+    else
+        rc = path.mid(0, path.size() - oldExt.size()) + ext;
+    return rc;
+}
 /**
  * Replaces placeholders by their values.
  *
index e3a221ccdb87a4aa518f65e84723ca1ba374ec22..fc00085c1b3b46a1164d364e9ac7754247450395 100644 (file)
@@ -45,6 +45,7 @@ public:
    }
    static ReString nodeOf(const ReString& filename);
    static QString pathAppend(const QString& base, const QString& path);
+   static QString replaceExtension(const QString& path, const QString& ext);
    static bool replacePlaceholders(QString& text,
       const QMap <QString, QString>& placeholders, QString* error);
    static void skipExpected(const ReString& text, QChar expected, int& index,